●
相関サブクエリー使ってる
● サブクエリーの内側の WHERE句で外側クエリーのテーブルのカ
ラム参照してるやつ。
– SELECT .., (SELECT .. FROM t2 WHERE t1.xx> t2.yy)
FROM t1 .. WHERE .. みたいな。
●
相関サブクエリーは外側クエリーからフェッチした行数だけサブク
エリーを実行するので、外側クエリーのテーブルが大きくなれば
なるほど一気に重くなる。
● CPU 使用率を跳ね上げることが多い。というか CPU 使用率が跳
ね上がったら大量アクセスかこれを疑う。
● パズルだと思って JOIN に書き換えるか、中間テーブルやアプリ
側に一度値を保持させてクエリーを分割する。
● EXPLAIN すら返ってこなくなるパターンはほぼこれ。
● PostgreSQL はこのへんもそつなくこなすイメージ。
30.
●
インデックスが足りない
● MyISAM はテーブルスキャンでも割と速いけれど、そのノリで
InnoDBに向かうと地獄が見える。
● MySQL が 1 つのリレーションで使えるインデックスは基本的に 1
つだけなので、重いクエリーには複合インデックスを作る。
– 基本その 1 、 WHERE 句の AND 条件でつながれているもの
を順番に並べる。
– 基本その 2 、それに ORDER BY で使われているカラムを足
す。
– SELECT .. FROM .. WHERE c4= xx AND c2= yy ORDER
BY c3 なら、 (c4, c2, c3)
– 不等号とか OR 演算子使ったりすると ORDER BY まで波及し
ないとか、 LIMIT 使ってるなら WHERE よりも ORDER BY を
狙ってインデックス作ると速いとかこれ以外にもコツはある。
● 特に COUNT は全てインデックスで解決できないと非常に重い。
831 さん、お便りありがとうございます。
MySQL はアホの子なので、難しいクエリーを投げ
るとなかなか返してくれません。 MySQL でも判るよう
な簡単なクエリーに書き換えたり、インデックスでヒント
をあげて下さい。
大事なことなのでもう一度言います。 MySQL はア
ホの子です。ナントカとハサミは使いようだと思って頑
張ってください。
●
そのままではスローログに載らないクエリー
● SET GLOBALlong_query_time= 0.3; SET GLOBAL
log_queries_not_using_indexes= 1; とかして 10 分くらいサンプリ
ングする。
– 大概死ぬほどスローログ吐くので、 pt-query-digest や
mysqldumpslow と併用。
– 予めログをローテートさせておかないと混じって見にくい。
● pager egrep -v "Sleep|handlersocket|Binlog Dump" からの SHOW
FULL PROCESSLIST を連打。
– 個人的にはこれお気に入り。
– TeraTerm 使ってると Recurring Command って設定があるの
で、これで 0.5 ~ 1 秒間隔くらいで連続実行させる。
– State に「今やってる処理」が表示されるので、ざっくりあたりを
つけられる。
37.
●
どこがイケてないんだかいまいち判らないクエリー
● まずは EXPLAIN
–Key で想定しているキーが使われているかどうか、 Key length
が想定している長さで使われているか。
● (int, datetime, varchar(32)) のキーなのに Key length が 4
だと、左端の int にしかキーが効いてない。
– Using filesort は意外と重い。 covering index か ORDER BY
狙いのキーを作る。
● オプティマイザーは ORDER BY 狙いのキーよりも
WHERE 狙いのキーの方を選びたがるので、 USE INDEX
でキーを狙い撃ちしてやる。
● SET profiling= 1; からのクエリー実行からの SHOW PROFILE;
– たまに遅い、というようなケースには不向き。
– 内部のステージごとに所要時間が表示されるので、再現性が
あるなら最強。
– 5.6 で deprecated に。