Mysql優化_ORDER BY和GROUP BY 的優化講解(單路排序和雙路排序)


ORDER BY 子句盡量使用Index方式排序,避免使用FileSort方式排序,盡可能在索引列上外城排序操作,遵照索引鍵的最佳左前綴。如果不在索引列上,FileSort有兩種算法,Mysql就要啟動雙路排序和單路排序。

什么是雙路排序和單路排序?

雙路排序:Mysql4.1之前是使用雙路排序,字面的意思就是兩次掃描磁盤,最終得到數據,讀取行指針和ORDER BY列,對他們進行排序,然后掃描已經排好序的列表,按照列表中的值重新從列表中讀取對數據輸出。也就是從磁盤讀取排序字段,在buffer進行排序,再從磁盤讀取其他字段。文件的磁盤IO非常耗時的,所以在Mysql4.1之后,出現了第二種算法,就是單路排序。

單路排序:從磁盤讀取查詢所需要的所有列,按照ORDER BY在buffer對它進行排序,然后掃描排序后的列表進行輸出,它的效率更快一些,避免了第二次讀取數據。並且把隨機IO變成了順序IO,但是它會使用更多的空間,因為它把每一行都保存在了內存里。

但是,問題來了,有可能單路排序算法一次拿不出數據,那么就還比雙路排序更消耗IO,效率更慢!


什么情況下會導致單路排序失效呢?
在sort_buffer中,單路排序要比雙路排序占很多空間,因為單路排序把所有的字段都取出,所以有可能取出的數據的總大小超出了sort_buffer的容量,導致每次只能讀取sort_buffer容量大小的數據,進行排序(創建tmp文件,多路合並),排完再取sort_buffer容量大小,再次排序...從而多次I/O。偷雞不成蝕把米。
比如:內存就是2M,一次查1000條數據剛好,也就是最大1000條數據,但是一次要查5000條,那么不夠了,照這樣需要查5次剛好,如果把2M改為10M,那么就剛好了

提高ORDER BY速度的技巧
1:ORDER BY時不要使用SELECT *,只查需要的字段。
   a:當查詢的字段大小綜合小於max_length_for_sort_data而且排序字段不是TEXT|BLOB類型時,會用改進后的算法---單路排序,否則用老算法---多路排序。假設只需要查10個字段,但是SELECT *會查80個字段,那么就容易把sort_buffer緩沖區用滿。
   b:兩種算法的數據都有可能超出sort_buffer的容量,超出之后,會創建tmp文件進行合並排序,導致多次I/O,但是用單路排序算法的風險會更大一些,所以要提高sort_buffer_size大小。
2:增大sort_buffer_size參數大小
不管用哪種算法,提高這個參數都會提高效率。當然要根據系統能力去提高,因為這個參數是針對每個進程的。
3:增大max_length_for_sort_data參數大小
提高這個參數,會增加用改進算法的概率。但是如果設的太高,數據總量超出sort_buffer_size的概率就增大,明顯症狀是高的磁盤I/O活動和低的處理器使用率。

 

為排序使用索引
MYSQL兩種排序方式:文件排序和掃描有序索引排序
Mysql能為排序和查詢使用相同的索引。也就是創建索引先把數據排序了,查詢的時候再利用索引,一舉兩得。

KEY a_b_c(a,b,c)
order by 能使用索引最左前綴

ORDER BY a
ORDER BY a,b
ORDER BY a,b,c
ORDER BY a DESC,b DESC,c DESC

如果where使用縮印的最左前綴定義為常量,則order by 能使用索引

WHERE a = const ORDER BY b,c WHERE a = const AND b = const ORDER BY c WHERE a = const AND b > const ORDER BY b,c

不適用索引進行排序

ORDER BY a ASC,b DESC, c DESC //排序不一致
WHERE g = const ORDER BY b,c //丟失a索引
WHERE a = const ORDER BY c //丟失b索引
WHERE a = const ORDER BY a,d //d不是索引的一部分
WHERE a in (....) ORDER BY b,c //對於排序來說,多個相等條件也是范圍查詢

GROUP BY的優化

GROUP BY實質上是先排序后進行分組,遵照索引的最佳左前綴。
當無法使用索隱裂,考慮增大max_length_for_sort_data和sort_buffer_size的參數設置。
WHERE 高於 HAVING,能寫在WHERE限定的條件就不要去HAVING限定了。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM