2016-07-27 60 views
0

這是InnoDB with MySQL 5.7的索引。MySQL - 相關級聯查詢集合的最佳索引

我有一組4個相關的級聯查詢:

SELECT DISTINCT A, COUNT(*) FROM MYTABLE 
    WHERE D IN ? AND A > ? 
    GROUP BY A ORDER BY A LIMIT 100 

SELECT DISTINCT B, COUNT(*) FROM MYTABLE 
    WHERE A = ? AND D IN ? AND B > ? 
    GROUP BY B ORDER BY B LIMIT 100 

SELECT DISTINCT C, COUNT(*) FROM MYTABLE 
    WHERE A = ? AND B = ? AND D IN ? AND C > ? 
    GROUP BY C ORDER BY C LIMIT 100 

SELECT E, F, G, H FROM MYTABLE 
    WHERE A = ? AND B = ? AND C = ? AND D IN ? AND ID > ? 
    ORDER BY ID LIMIT 100 

什麼是最低組索引(ES),使得所有的查詢可以使用索引(ES)的一個由每個修剪的他們的WHERE子句,並使用它/他們來加快ORDER BY?

據我瞭解關於複合索引,我需要:

CREATE INDEX INDEX01 ON MYTABLE (D, A) 

CREATE INDEX INDEX02 ON MYTABLE (A, D, B) 

CREATE INDEX INDEX03 ON MYTABLE (A, B, D, C) 

CREATE INDEX INDEX04 ON MYTABLE (A, B, C, D) 

(ID是主鍵列)

這是正確的嗎?

我想如果我重新排列WHERE子句,我可能用只一個綜合指數:

SELECT DISTINCT A, COUNT(*) FROM MYTABLE 
    WHERE D IN ? AND A > ? 
    GROUP BY A ORDER BY A LIMIT 100 

SELECT DISTINCT B, COUNT(*) FROM MYTABLE 
    WHERE D IN ? AND A = ? AND B > ? 
    GROUP BY B ORDER BY B LIMIT 100 

SELECT DISTINCT C, COUNT(*) FROM MYTABLE 
    WHERE D IN ? AND A = ? AND B = ? AND C > ? 
    GROUP BY C ORDER BY C LIMIT 100 

SELECT E, F, G, H FROM MYTABLE 
    WHERE D IN ? AND A = ? AND B = ? AND C = ? AND ID > ? 
    ORDER BY ID LIMIT 100 

那麼我就需要:

CREATE INDEX INDEX01 ON MYTABLE (D, A, B, C) 

是正確的嗎?

但是,我認爲以這種方式排列WHERE子句並不是最優的。之所以總是試圖把「IN」操作,並作爲最後2 WHERE子句是「>」運行:

  1. 的MySQL需要做的「IN」更多的工作(有多個值進行比較)與「=」相比,可能(由於我的數據集和我正在過濾的內容),較少的行將被這個子句修剪。

  2. 「>」操作主要用於分頁目的。即在某些情況下,由於此條款的限制,幾乎不會修剪。

我的理解是否正確?

+0

這取決於你的數據類型爲真實世界的健康系統。它們是精簡還是加載varchar(255) – Drew

+0

請參閱[this](http://stackoverflow.com/a/38002986)有關Optimizer和'IN' – Drew

回答

1

執行不是在同一個查詢中同時執行DISTINCTGROUP BY。由於總數(COUNT),您可能需要GROUP BY,所以折騰DISTINCT

GROUP BY x ORDER BY x LIMIT 100,以下可能幫助:

INDEX(x) -- or INDEX(x, ...) 

因此,包括,以防萬一。我的意思是,優化器可能選擇使用索引處理GROUP BY + ORDER BY + LIMIT而不是看WHERE。如果決定使用WHERE,然後...

WHERE D IN ? AND A > ? 
INDEX(D, A) 

可以越級(「MRR」)的D'S和掃描A的,但它可以不消耗任何GROUP BYORDER BY

WHERE A = ? AND D IN ? AND B > ? 
INDEX(A, D, B) 

將任何'='事情先放入索引中。其餘的邏輯如上。

WHERE A = ? AND B = ? AND D IN ? AND C > ? 
INDEX(A, B, D, C) or INDEX(B, A, D, C) 

(相同的邏輯)

WHERE A = ? AND B = ? AND C = ? AND D IN ? AND ID > ? 
INDEX(A,B,C, -- in any order, then 
     D, ID) -- at end, in this order. 

因此,對於該組的4條語句,我建議4個或5個指標,在給定的順序:

INDEX(D, A) 
INDEX(A, D, B) 
INDEX(B, A, D, C) -- I picked that one to get one starting with B 
INDEX(c, B, A, D, ID) 
INDEX(ID) -- but don't add if you already have `PRIMARY KEY(ID)` 

作爲獎勵,在這些指數中,前3個指數具有「覆蓋」指標,給您額外的獎勵。最後的SELECT需要一個9列索引來「覆蓋」;那太多了。

WHERE中AND'd事物的順序沒有區別。所以,我想我可以忽略你的問題的其餘部分。

(警告:之前約5.6,在跨越不存在,所以「最好的」設置指標是別的東西。)