Mysql group by,order by,dinstict優化

1.order by優化mysql

2.group by優化算法

3.Dinstinct 優化sql

 

1.order by優化函數

實現方式:性能

1. 根據索引字段排序,利用索引取出的數據已是排好序的,直接返回給客戶端;優化

2. 沒有用到索引,將取出的數據進行一次排序操做後返回給客戶端。spa

EXPLAIN SELECT m.id,m.subject,c.content FROM group_message m,group_message_content c WHERE m.group_id = 1 AND m.id = c.group_msg_id ORDER BY m.user_id\G;

optimizer對query進行了優化,它會按照m.user_id上的索引順序來訪問數據,這樣獲取的數據已是排好序的。指針

這種利用索引實現數據排序的方法是 MySQL 中實現結果集排序的最佳作法,利用已有的索引避免實際的排序計算所帶來的資源消耗。blog

 

若是沒有用到索引,mysql就會將取出的數據按照必定的排序算法進行排序,而後再把排好序的數據返回給客戶端。mysql中主要使用兩種排序算法:排序

1. 取出用於排序的條件字段和指向相應數據行的指針,在sort buffer中對條件進行排序,排好序以後利用指針取出數據行中的請求數據,而後返回給客戶端;

2. 取出用於排序的條件字段和其它全部請求數據,將不用於排序的字段存放在一塊內存中,而後在sort buffer中對條件字段進行排序,排好序後利用行指針將在內存中的數據進行匹配合並結果集,而後將排好序的數據返回給客戶端。(減小數據的二次訪問,節省了IO操做)

3.當用於排序的字段存在在多個表中,或者在排序以前要先通過join操做,mysql必須先把join的結果集放入一個臨時表,以後再把臨時表中的數據取到sort buffer裏進行排序

優化方式:

1. 加大max_length_for_sort_data參數的設置。當須要取出的全部數據長度小於這個參數的值的時候,mysql將採用第二重排序算法,不然,使用第一種算法,因此只要內存充足就能夠設置足夠大的值來讓mysql採用改進的排序算法。

2. 去掉沒必要要的字段。

3. 增大sort_buffer_size參數的值。當mysql對條件字段進行排序時,若是須要排序字段的總長度大於該參數的值的時候,mysql就會對須要排序的字段使用臨時表進行分段,這樣也會有性能的消耗。

 

2.group by優化

group by的實現過程除了要使用排序操做外,還要進行分組操做,若是使用到一些聚合函數,還要進行相應的聚合計算

實現方式:

1. 使用鬆散(Loose)索引掃描實現group by,所謂的鬆散索引掃描,就是mysql不須要掃描全部知足條件的索引鍵便可完成group by操做

2. 使用緊湊(Tight)索引掃描實現group by,緊湊索引與鬆散索引最主要的區別就是在須要掃描索引的時候,緊湊索引讀取全部知足條件的索引鍵,而後再來使用group by操做獲得相應的結果。

3.當optimizer沒法找到合適的索引能夠利用的時候,就會選擇將讀取的數據放入臨時表中來完成group by操做。group by操做想要利用索引,必須知足group by字段必須同時存放於同一個索引中,且該索引是一個有序索引,並且,使用不一樣的聚合函數也會影響是否使用索引來實現group by操做

優化方式:

1. 儘量利用索引而且是鬆散索引來完成group by操做,這的依靠調整索引或者調整query來實現;

2. 當沒法利用索引的時候,必需要提供足夠的sort_buffer_size來供mysql完成排序操做,以前介紹過,否則mysql會將須要排序的字段進行分段排序,會影響性能。除此以外儘可能不要對大結果集進行group by操做,由於一旦數據量超過系統最大臨時表大小時,mysql會將臨時表裏的數據copy到磁盤上而後再進行操做,性能會成數量級的降低。

 

3.Dinstinct 優化

實現方式:

     distinct的實現原理同group by相似,實現過程只是在group by以後只取出每一組中的第一條記錄,因此distinct一樣能夠利用鬆散或者緊湊索引來實現,不一樣的是,當沒法利用索引實現distinct時,mysql一樣會將數據取出放進一個臨時表,不過不會對臨時表進行排序操做。

優化方式:

     儘可能使用索引,沒法使用索引的時候,確保不要在大結果集上進行distinct操做,磁盤上的IO操做和內存中的IO操做性能徹底不是一個數量級的差距。

相關文章
相關標籤/搜索