![](/img/trans.png)
[英]Slow SQL query: using the same table in two different joins causes query to become 10x slower!
[英]Mysql: same query, same number of resulting rows, no joins, 10x slower?
我正在包含〜3M行的innodb表上運行以下兩個查詢。 由於某種原因,第一個查詢花費不到一秒鍾的時間才能返回168,199行,而第二個查詢花費8秒並返回167,159行? 返回幾乎相同結果所需的時間增加了10倍?
SELECT count(idActivities) as amt
FROM Activities
WHERE Data_Type='email'
AND Status='sent'
AND (Created > '2019-07-17 00:00:00'
AND Created <= '2019-08-17 00:00:00');
SELECT count(idActivities) as amt
FROM Activities
WHERE Data_Type='email'
AND Status='sent'
AND (Created > '2019-08-17 00:00:00'
AND Created <= '2019-09-17 00:00:00');
如果我從第二條語句中刪除其他where子句,例如
SELECT count(idActivities) as amt
FROM Activities
WHERE (Created > '2019-08-17 00:00:00'
AND Created <= '2019-09-17 00:00:00');
查詢時間下降到半秒。 如果我在語句中添加一個額外的where子句,例如Data_Type =或Status =,它將跳回到8加秒。
我也嘗試過將日期向任一方向移動幾天,但這不會影響查詢時間。
該表在idActivities,Data_Type,Status和Created上建立索引。
該服務器運行5GB Ram,8核,並且具有innodb_buffer_pool_size = 3G,InnoDB緩沖區使用率為49%。
我在不同的服務器上嘗試了相同的查詢,結果大約在大約4秒的同一時間,這仍然很慢。
我注意到的唯一區別是,即使表實際上是相同的,Data_Type列的基數也有所不同(這是前一天的備份)。
在理解如何縮短查詢時間方面會有所幫助或幫助,我將不勝感激。 運行“ DISTINCT(Data_Type)”僅返回整個表的13行。
編輯謝謝Salman A,通過添加以下復合索引,極大地提高了兩個查詢的性能:
CREATE INDEX ix_1 ON活動(已創建,Data_Type,狀態);
我建議創建以下覆蓋索引:
CREATE INDEX ix_1 ON t (Data_Type, Status, Created)
列的順序很重要。 高基數列通常放在最前面,但是對於此特定查詢,您需要將創建的列放在最后,因為它涉及范圍比較(前兩個需要相等比較)。
您需要在此處定義具有特定列順序的組合索引。 一般的經驗法則是:
應該為WHERE
子句內並由AND
子句連接的所有列賦予第一優先級,並使用=
, IS NULL
或<=>
它們與常量值進行比較 。 因此,在您的查詢中,此后有兩列: Data_Type
和Status
。
可以優先考慮以下三種情況:
GROUP BY
子句中特定順序的列(如果存在)。 ORDER BY
子句中特定順序的列(如果存在) 在這種情況下, Created
是一個Range條件,因此我們將在最后將該列添加到索引中,因為在遇到range條件時,MySQL在該列處停止,並且不再訪問索引中的其他列。
因此,您基本上需要定義以下索引:
ALTER TABLE Activities ADD INDEX(Data_Type, Status, Created);
引用里克·詹姆斯的筆記 :
當您具有可以按任意順序排列的復合索引時,各個列的基數在選擇順序時都沒有關系。 整個索引的基數很重要。
當您遇到此類意外行為時,我總是通過讓服務器解釋其工作情況來檢查服務器的工作情況。
您可以在查詢開始時使用EXPLAIN關鍵字進行此操作。 我猜較慢的查詢正在掃描整個表以獲取結果集
https://dev.mysql.com/doc/refman/8.0/zh-CN/using-explain.html
順便提一下:除非您的data_type和status列具有很高的選擇性(可能不會)。 我猜他們是毫無意義的索引。 通常,在狀態狀態列占很大比例時,索引狀態列只是一個好主意。 即95%關閉“狀態”和5%“打開”,您有一個查詢要查找所有打開狀態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.