mysql 優化order by

jopen 8年前發布 | 9K 次閱讀 MySQL 數據庫服務器

MySQL 中有兩種排序方式:
    1.通過有序索引掃描直接返回有序數據,這種方式在使用explain分析查詢的時候顯示為using index,
      不需要額外的排序,操作效率較高。

mysql> explain select count(id) from warning_repaired\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: warning_repaired
         type: index
possible_keys: NULL
          key: id
      key_len: 4
          ref: NULL
         rows: 499471
        Extra: Using index
1 row in set (0.00 sec)

    2.通過對返回數據進行排序,也就是通常所說的filesort排序,所有不是通過索引直接返回排序結果的排序
      都叫filesort排序。 filesort并不代表通過磁盤文件進行排序,而只是進行了一個排序操作,至于排序操作
      是否使用了磁盤文件或者臨時表等,則取決于MySQL服務器對排序參數的設置和需要排序數據的大小。


     Filesort是通過相應的排序算法,將取得的數據在sort_buffer_size系統變量設置的內存排序區中進行排序,
    如果內存裝載不下,它就會將磁盤上的數據進行分塊,再對各個數據進行排序,然后將各個塊合并成有序的
    結果集。sort_buffer_size 設置的排序區是每個線程獨占的,所以同一個時刻,MySQL 中存在多個
    sort buffer 排序區。
    
    了解了MySQL 排序方式,優化的目標就清楚了:盡量減少額外的排序,通過索引直接返回有序數據。
    Where 條件和ORDER BY使用相同的索引,并且ORDER BY 的順序和索引順序相同, 并且ORDER BY的字段都是
    升序或者都是降序。否則肯定需要額外的排序操作,這樣就會出現Filesort.


Filesort的優化:
    通過創建合適的索引能夠減少filesort的出現,但是某些情況下,條件限制不能讓Filesort消失,那就需要
    想辦法加快filesort的操作。對于filesort, MySQL 有兩種排序算法。
    1.兩次掃描算法(two passes): 首先根據條件取出排序字段和行指針信息,之后在排序區Sort buffer 中排序,如果排序區sort bufer 不夠,則在臨時表Temporary Table中存儲排序結果,完成排序后,根據行指針
    回表讀取數據。該算法是在mysql4.1之前采用的算法,需要兩次訪問數據,第一次獲取排序字段和行指針信息。
    第二次根據行指針獲取記錄,尤其是第二次讀取操作可能導致大量隨機I/O;優點是排序的時候內存開銷小。
    2. 一次掃描算法(single Pass):一次性取出滿足條件的行的所有字段,然后在排序區sort buffer 中排序后直接
    輸出結果集。排序的時候內存開銷大比較大。但是排序效率比兩次掃描算法要高。
    
    MySQL 通過比較系統變量max_length_for_sort_data 的大小和Query 語句取出的字段總大小來判斷使用
    哪種算法。如果max_length_for_sort_data 更大,那么使用第二種優化之后的算法,否則使用第一種算法。
    
    適當的加大系統變量max_length_for_sort_data的值,能夠讓MySQL選擇更優化的Filesort排序算法。但是,如果
    max_length_for_sort_data設置過大,就會造成CPU利用率過低和磁盤I/O過高,CPU和I/O利用平衡就足夠了。
    
    適當加大sort_buffer_size排序區,盡量讓排序在內存中完成,而不是通過創建臨時表放在文件中進行;
    當然也不能無限加大sort_buffer_size排序區,因為sort_buffer_size參數是每個線程獨占的。設置過大,
    會導致服務器SWAP嚴重,要考慮數據庫活動連接數和服務器內存的大小適當設置排序區。
    
    盡量只使用必要的字段,SELECT 具體的字段名稱,而不是SELECT * 選擇所有字段

    這樣可以減少排序區的使用,提高SQL 性能。

學習自《深入淺出mysql》

來自: http://my.oschina.net/lvhuizhenblog/blog/552730

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!