我在Debian 8機器上使用mysql 5.5.52,有時候我們有一個慢速查詢(> 3s),通常花費0.1s。我已經開始使用explain命令來查找正在發生的事情。mysql優化器中的奇怪查詢
這是查詢和解釋信息
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,裁判,行,額外
1簡單的方塊指數用戶名, MESSAGE_ID MESSAGE_ID 4 443使用其中
1點,簡單的信息eq_ref PRIMARY PRIMARY 4 box.message_id 1使用其中
它看起來更好,但我不明白爲什麼它使用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建議。
你能顯示產生第二個解釋的查詢嗎? – ysth
啊,你的意思是你改變了從message.id到box.message_id的順序? – ysth
'AND \'messages \'。() - INTERVAL 10分鐘> NOW()' - >'AND \'messages \'。\'date \'> NOW() - INTERVAL 10 MINUTE'。當不需要時不要對列進行任何轉換。 (在這種情況下,這可能不是問題,但只是一個參考)。 – Pred