[英]Weird query in mysql optimizer
我在Debian 8機器上使用mysql 5.5.52,有時我們的查詢速度慢(> 3s),通常花費0.1s。 我從explain命令開始,以查找正在發生的事情。
這是查詢和解釋信息
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,表,類型,可能的鍵,鍵,key_len,引用,行,額外
1 SIMPLE框索引user_id,message_id,message_id 4443在何處使用
1條簡單消息eq_ref PRIMARY PRIMARY 4 box.message_id 1使用
看起來更好,但是我不明白為什么要使用message_id索引,更糟糕的是,現在查詢需要1.5秒而不是最初的0.1秒
編輯:
強制查詢使用user_id索引,我得到與初始查詢相同的結果(0.1s),但沒有臨時查詢
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的建議檢查組合索引。
計算要比較的字段值不是一個好主意。 那么您將獲得一個全表掃描。 MySQL必須先檢查每個ROW,然后才能檢查條件。 最好在恆定條件下執行此操作。 然后MySQL可以使用索引(如果此字段中有一個)
從
AND messages.date + INTERVAL 10 MINUTE > NOW()
至
AND messages.date > NOW() - INTERVAL 10 MINUTE
臨時和文件排序在這里還不錯; 它們是必需的,因為使用最佳索引(user_id)並不會自然產生按您要求的順序排序的記錄。
結合使用user_id和message_id索引可能會更好,但是最終結果也會更糟。 取決於您的確切數據。
我不清楚您是否看到更長的查詢某些用戶ID或相同的用戶ID有時需要更長的時間。
更新:似乎有一個組合的索引並按box.user_id,box.message_id更改順序可以解決您的問題,至少對於沒有大量已刪除郵件的用戶而言。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.