さあ、今日も頑張って他のチームからの依頼で調査していました〜
調べ物のついでに恒常的にDBの負荷が高くなる処理について調べてみた。
投げているSQLを解析してみたところ次のようになっていた。
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra| +----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+ | 1 | SIMPLE | tweet | index | index_b | index_a | 4 | NULL | 1 | Using where | +----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+
・
・
・
・
・
・
typeの項がindexになってるwww
そりゃ、indexはインデックスをフルスキャンしているのでこのクエリ遅いはずだわ。
誰が作ったか知らんがEXPLAINしてtypeがALLかindexになっているクエリは投げちゃダメだって!!
漢(オトコ)のコンピュータ道: MySQLのEXPLAINを徹底解説!!
MySQL :: MySQL 4.1 リファレンスマニュアル :: 5.2.1 EXPLAIN 構文(SELECT に関する情報の取得)
何でこんなことなっているんだと隣のカラムを順番に見ていくと
keyの項目が index_a になっている!
これはこのクエリでindex_aを使っているということを示しているんだがこのクエリの場合index_aは適切じゃないんだよ。
possible_keysにindex_bが存在していて本来ならこちらを使って欲しいんだけど、
MySQLのオプティマイザが勝手に判断して不適切なindexになっている。
この場合はクエリが使うインデックスを指定するにはFORCE INDEX構文を使う。
でFORCE INDEX使ってやったあとにEXPLAINした結果がこんな感じ。
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra| +----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+ | 1 | SIMPLE | tweet | range | NULL | index_b | 4 | NULL | 1 | Using where | +----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+
typeがindexからrangeになっている。
rangeはインデックスを用いた範囲検索なのでこれだけでも相当クエリのパフォーマンスが改善する。
keyもindex_bになっているのでこれでOK。
クエリの実行時間は環境によるのでどれぐらい改善するかはわからないが、
うちの環境では実行時間は半分になったのでまぁ相当効果があった。
MySQL :: MySQL 5.1 リファレンスマニュアル (オンラインヘルプ) :: 8.2.8.2 インデックスヒントの構文
MySQL :: MySQL 4.1 リファレンスマニュアル :: 6.4.1 SELECT 構文
-
-
- -
-
テーブル名とEXPLAINの結果の細部などは適当に作ったので、
ところどころおかしいですが、大事な部分はちゃんとしているのでつっこみ入れないでください。