[英]MySQL query optimization. Avoiding temporary & filesort
目前我有一個近 100 萬行的表,我需要從中查詢。 我需要做的是從給定的產品ID列表中對它們包含的產品數量進行堆棧排名。
SELECT count(productID) AS commonProducts, packageID
FROM supply
WHERE productID IN (2,3,4,5,6,7,8,9,10)
GROUP BY packageID
ORDER BY commonProducts
DESC LIMIT 10
查詢工作正常,但我想改進它。 我在 productID 和 packageID 上嘗試了一個多列索引,但它似乎尋求更多的行,而不僅僅是為每個列設置一個單獨的索引。
MySQL說明
select_type: SIMPLE
table: supply
type: range
possible_keys: supplyID
key: supplyID
key_len: 3
ref: null
rows: 996
extra: Using where; Using temporary; Using filesort
我主要擔心的是查詢正在使用臨時表和文件排序。 我怎么能 go 關於優化這個查詢? 我認為最大的問題是 count() 和 count() 結果的 ORDER BY。
您可以使用Dependent Subquery刪除臨時表:
select * from
(
SELECT count(productID) AS commonProducts, s.productId, s.packageID
FROM supply as s
WHERE EXISTS
(
select 1 from supply as innerS
where innerS.productID in (2,3,4,5,6,7,8,9,10)
and s.productId = innerS.productId
)
GROUP BY s.packageID
) AS t
ORDER BY t.commonProducts
DESC LIMIT 10
內部查詢鏈接到外部查詢並保留索引。 您會發現任何對 commonProducts 進行排序的查詢,包括上述查詢,都將使用文件排序,因為count(*)
絕對沒有被索引。 但不要害怕,filesort 只是一個花哨的排序詞——mysql 可以選擇使用有效的內存排序——無論你現在使用它還是作為索引臨時表的合並排序,你都將擁有在某處支付排序費用。 但是,這種情況非常好,因為文件排序一旦達到您設置的LIMIT
就會停止排序。 它不會對整個 commonProducts 列表進行排序。
更新
如果要一直運行此查詢,我建議(不要太花哨)在供應表上設置觸發器以更新跟蹤此類計數器的合法表。
創建一個臨時結果集:
SELECT TMP.*
FROM ( SELECT count(productID) AS commonProducts, packageID
FROM supply
WHERE productID IN (2,3,4,5,6,7,8,9,10)
GROUP BY packageID
) AS TMP
ORDER BY commonProducts
DESC LIMIT 10
也許這不是最優雅的方式,我不能保證它會更快,因為一切都取決於您的特定數據。 但在某些情況下,這會產生更好的結果:
SELECT count(*) AS commonProducts, packageID
FROM (
SELECT packageID FROM supply WHERE productID = 2
UNION ALL
SELECT packageID FROM supply WHERE productID = 3
UNION ALL
.
.
.
SELECT packageID FROM supply WHERE productID = 10
) AS t
GROUP BY packageID
ORDER BY commonProducts DESC
LIMIT 10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.