MySQL IN演算子が遅い時の対策
topコマンドで見た時にいつもmysqldのCPU使用率が300前後になっています
改善方法など全くといっていいほどわからないのですが、まずslow-logを覗いてみたところ
SELECT `a_id`, `b_id`, `hoge`
FROM `table1`
WHERE `a_id` IN (10,27,37,38,46,47,51,69,73,82,86,90,103,110,125,129,134,135,136,137,139,142,148,150,161,168,181,184,187,191,192,198,200,206,215,222,230,231,249,264,266,270,271,302,315,338,342,349,360,361,366,376,383,385,399,405,406,410,412,424,427,432,438,444,454,456,457,462,480,483,484,487,488,492,493,494,506,509,517,549,559,573,574,578,579,586,587,594,597,599,609,612,617,619,625,629,632,633,637,642,646,679,681,684,687,688,689,691,692,696,698,699,700,708,716,738,739,740,742
,755,758,764,767,768,772,774,778,780,782,783,786,787,792,793,795,796,799,802,807,808,810,811,815,816,817,819,821,823,826,827,828,829,831,833,834,839,840,841,846,849,854,855,856,857,858,859,860,861,864,872,879,881,882,884,888,890,892,893,894,896,899,907)
ORDER BY `updatetime` DESC
LIMIT 0, 100;
このようなクエリが1秒以上かかっていました。
`table1`と`table2`は`a_id`で紐付いていて、事前に`table2`に入っているa_idの一覧を取得してから上記のクエリを作成しています。
`table1`のスキーマを確認したところ
INDEX a_id(`a_id`)
INDEX updatetime(`updatetime`)
となっていました。
(素人ながらに
INDEX idx1(`a_id`, `updatetime`)
とするべきだったのでは…と思ったのですがALTER TABLEで追加してみたところ、結果は変わりませんでした。)
EXPLAINしてみたところ
1 | SIMPLE | feed | range | a_id,i1 | a_id | 5 | NULL | 237900 | Using where; Using filesort
と返ってきました。
このような状態では、どのように対策するのが良いのでしょうか。
決まった正解はないのかもしれないですが、考えられる可能性で試すべき項目を教えて頂ければ幸いです。
・table2のidに紐付いたtable1の情報を取り出したい場合の適切な設計
・適切なSQL文
・適切なインデックスの貼り方
などをご教授いただけると嬉しいです。
21時~0時くらいの時間帯になるとアクセスが増えload averageが10前後になってしまい、いつサーバーが落ちるかとヒヤヒヤしています…
是非ご回答宜しくお願い致します。
お礼
どうもありがとうございました。 参考になりました。