MySQL有關Group By的優化

    昨天我寫了有關MySQL的loose index scan的相關博文(http://www.cnblogs.com/wingsless/p/5037625.html),後來我發現上次提到的那個優化方法中主要的目的就是實現loose index scan,而在執行計劃的層面上看,Extra信息中應該是「Using index for group-by」。這樣看來,可能MySQL在處理distinct時和group by用了一樣的優化手段,即走索引,進行loose index scan。那麼今天我研究了一下官方文檔,發現確實如此。html

    其實對於group by來說,最通常的實現方法就是進行一次全表掃描,將全部的group by的行按照順序存放在一個temporary table中,而後在進行分組識別或者進行聚合操做。這樣問題就是太複雜,時間上要很久,空間上的消耗也不小。這時,MySQL能夠利用索引來優化group by。less

    這裏就能夠講講什麼叫作loose index scan了,根據官方的定義,這種方法只須要掃描索引中的少部分數據,而不是全部知足where條件的數據,因此這個方法叫作loose index scan。函數

    下面是什麼狀況下可使用loose index scan的狀況:測試

    1 單一表查詢優化

    2 Group by中只有最左前綴列,沒有其餘列spa

    3 只支持max和min聚合,並且,要聚合的列必須是group by中列所在的索引。code

    4 未被group by引用的索引其餘部分必須是常量(這句我不是很理解)htm

    5 不支持前綴索引。blog

    假設t1(c1, c2, c3, c4)表有一個索引包括c1, c2, c3列,如下這些查詢都是能夠進行loose index scan的:索引

    

SELECT c1, c2 FROM t1 GROUP BY c1, c2;
SELECT DISTINCT c1, c2 FROM t1;
SELECT c1, MIN(c2) FROM t1 GROUP BY c1;
SELECT c1, c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;
SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > const GROUP BY c1, c2;
SELECT c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;
SELECT c1, c2 FROM t1 WHERE c3 = const GROUP BY c1, c2;

    這些都是抄的官方文檔,正確性未徹底驗證。  

    下面這些SQL都沒有辦法使用loose index scan:

    

-- 由於聚合函數不是max或者min
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;

-- 由於不符合最左前綴原則
SELECT c1, c2 FROM t1 GROUP BY c2, c3;

-- 查詢涉及到了索引的一部分,緊跟group by中的列,可是沒有常量等值語句,加上 
SELECT c1, c3 FROM t1 GROUP BY c1, c2;WHERE c3 = const就行了const就行了

     另一些聚合函數也是能夠用到loose index scan的,好比:AVG(DISTINCT), SUM(DISTINCT), 和COUNT(DISTINCT)

     如下這些語句也能夠:

     

SELECT COUNT(DISTINCT c1), SUM(DISTINCT c1) FROM t1;

SELECT COUNT(DISTINCT c1, c2), COUNT(DISTINCT c2, c1) FROM t1;

      不少語句都是從5.7的文檔上摘抄下來的,正確性沒有獲得驗證,雖然說官方文檔是權威,可是盡信書不如無書,以及紙上得來終覺淺,絕知此事須躬行,明天週末,我逐條測試,而後再更。

相關文章
相關標籤/搜索