私はDebian 8マシンでmysql 5.5.52を使用していますが、時には0.1sを費やす低速クエリ(> 3s)があります。私は何が起きているのかを見つけるためにexplainコマンドを使い始めました。mysqlオプティマイザの奇妙なクエリ
これは私が一時テーブルとfilesortレコードが悪いものであることを知っている、と私は問題は順序キーが最初のテーブルに属していないことであると仮定し、クエリと説明情報
explain
SELECT
`box`.`message_id` ID
, `messages`.`tipo`
, `messages`.`text`
, TIME_TO_SEC(TIMEDIFF(NOW(), `messages`.`date`)) `date`
FROM (`box`)
INNER JOIN `messages` ON `messages`.`id` = `box`.`message_id`
WHERE `box`.`user_id` = '1010231' AND `box`.`deleted` = 0
AND `messages`.`deleted` = 0
AND `messages`.`date` + INTERVAL 10 MINUTE > NOW()
ORDER BY `messages`.`id` ASC LIMIT 100;
id| select_type| table | type | possible_keys | key | key_len| ref | rows | Extra
1|SIMPLE |box |ref |user_id,message_id|user_id| 4|const | 2200 |Using where; Using temporary; Using filesort
1|SIMPLE |messages|eq_ref|PRIMARY |PRIMARY| 4|box.message_id| 1 |Using where
ですクエリ(ボックス)と、それはbox.message_idする変更、説明情報
ID、SELECT_TYPE、テーブル、タイプ、possible_keys、キー、key_lenに、REF、行、エクストラ
1 SIMPLEボックス指数でありますユーザーID、
1つのSIMPLEメッセージを使用してPRIMARY PRIMARY 4 box.message_id 1でeq_ref使用MESSAGE_ID MESSAGE_ID 4 443どこ
それは今、最悪、MESSAGE_IDインデックスを使用して、そしてだなぜそれが良く見えますが、私は理解していませんクエリが1.5秒の代わりに、最初の0.1秒
編集取ります
はuser_idのインデックスを使用するクエリを強制的に、私は最初のクエリとしてではなく、一時的な
せずに同じ結果(0.1秒)を取得しますexplain
SELECT
`box`.`message_id` ID
, `messages`.`tipo`
, `messages`.`text`
, TIME_TO_SEC(TIMEDIFF(NOW(), `messages`.`date`)) `date`
FROM (`box` use index(user_id))
INNER JOIN `messages` ON `messages`.`id` = `box`.`message_id`
WHERE `box`.`user_id` = '1010231' AND `box`.`deleted` = 0
AND `messages`.`deleted` = 0
AND `messages`.`date` + INTERVAL 10 MINUTE > NOW()
ORDER BY `box`.`message_id` ASC LIMIT 100;
id| select_type| table | type | possible_keys | key | key_len| ref | rows | Extra
1|SIMPLE |box |ref |user_id,message_id|user_id| 4|const | 2200 |Using where; Using filesort
1|SIMPLE |messages|eq_ref|PRIMARY |PRIMARY| 4|box.message_id| 1 |Using where
一時的にスキップするのが最初のクエリよりも優れていると思っています。次のステップは、ysthが推奨するようにインデックスを組み合わせてチェックする方法です。
2番目の説明が作成されたクエリを表示できますか? – ysth
ああ、注文をmessage.idからbox.message_idに変更したということですか? – ysth
'AND \' messages \ 'です。インターバル10分> NOW() ' - >' AND \ 'メッセージ\'。\ '日付\'> NOW() - インターバル10分。必要でないときに列を変換しないでください。 (これはこの場合問題ではないかもしれませんが、FYIだけです)。 – Pred