mysql 優化order by

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

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

    2.經過對返回數據進行排序,也就是一般所說的filesort排序,全部不是經過索引直接返回排序結果的排序
      都叫filesort排序。 filesort並不表明經過磁盤文件進行排序,而只是進行了一個排序操做,至於排序操做
      是否使用了磁盤文件或者臨時表等,則取決於MySQL服務器對排序參數的設置和須要排序數據的大小。
算法

mysql> explain select *  from warning_repaired order by start_time desc\G;          
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: warning_repaired
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 499471
        Extra: Using filesort
1 row in set (0.00 sec)

     Filesort是經過相應的排序算法,將取得的數據在sort_buffer_size系統變量設置的內存排序區中進行排序,
    若是內存裝載不下,它就會將磁盤上的數據進行分塊,再對各個數據進行排序,而後將各個塊合併成有序的
    結果集。sort_buffer_size 設置的排序區是每一個線程獨佔的,因此同一個時刻,MySQL 中存在多個
    sort buffer 排序區。
    
    瞭解了MySQL 排序方式,優化的目標就清楚了:儘可能減小額外的排序,經過索引直接返回有序數據。
    Where 條件和ORDER BY使用相同的索引,而且ORDER BY 的順序和索引順序相同, 而且ORDER BY的字段都是
    升序或者都是降序。不然確定須要額外的排序操做,這樣就會出現Filesort.sql

mysql> explain select domain_moid, start_time  from warning_repaired order by domain_moid desc\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: warning_repaired
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 499471
        Extra: Using filesort
1 row in set (0.00 sec)

ERROR: 
No query specified

mysql> alter table warning_repaired add index domain_moid_start_time(domain_moid, start_time);        
Query OK, 0 rows affected (8.32 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select domain_moid, start_time  from warning_repaired order by domain_moid desc\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: warning_repaired
         type: index
possible_keys: NULL
          key: domain_moid_start_time
      key_len: 115
          ref: NULL
         rows: 499471
        Extra: Using index
1 row in set (0.00 sec)

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》dom

參考文章:
性能

http://my.oschina.net/wojibuzhu/blog/118035學習

相關文章
相關標籤/搜索