Mysql
查詢等式的最佳索引策略一種一種A, 範圍乙乙B, 通過…分組CCC, AND 排序方式count(P)C○你n噸(磷)count(P)
我有一個表現不佳的查詢:
SELECT user_id, count(item_id) as count FROM table items WHERE category = 'magazine' AND created_at > 1384754400 GROUP BY user_id ORDER BY count(item_id) desc LIMIT 100
為了優化此查詢,最佳索引策略是什麼?
表詳細資訊
具有以下結構/基數的5 億條記錄:
PRIMARY KEY (item_id)
- 基數:500 Muser_id
- 基數:~ 25 Mcategory
- 基數:~ 2.5 Mcreated_at
- 基數:~ 150 M索引:
- 我對每個 user_id、category 和 created_at 欄位都有單獨的索引
我還有以下覆蓋索引:
- (
category
,user_id
) -這是查詢優化器在執行解釋時的預設值- (
category
,created_at
)- (
category
,created_at
,user_id
) -這是我試圖創建的一個以優化此查詢,但是,它似乎並沒有很好地工作。
如果您只想針對此查詢進行優化。這是最好的索引:
ALTER TABLE items ADD INDEX (category, created_at, user_id)
這優化了過濾器的值,從而減少了您接觸的數據總量。通過在查詢末尾添加
user_id
,可以使索引覆蓋並節省您對主索引的查找。item_id
我們可以假設它
item_id
不是 NULL(因為它是 PRIMARY 索引)。但是,由於 MySQL 優化器非常愚蠢,您可能需要像這樣重寫:
SELECT user_id, SUM(count) AS count FROM ( SELECT category, created_at, user_id, COUNT(*) as count FROM items WHERE category = 'magazine' AND created_at > 1384754400 GROUP BY category, created_at, user_id ) AS d GROUP BY user_id ORDER BY count DESC LIMIT 100
我會刪除所有索引並重新開始。我認為一個類別索引就足夠了,或者最多一個(類別,created_at)。給定一個類別,應該有大約 200 個匹配項,所以這取決於 created_at 過濾器是否丟棄了很多行。您能否顯示查詢計劃和數字來驗證查詢的執行情況?我也不知道它是否重要,但 count(1) 也足夠了,而不是命名一個列。