1. 程式人生 > >《深入淺出MySQL》讀書筆記五:SQL優化

《深入淺出MySQL》讀書筆記五:SQL優化

一、SQL優化的一般步驟

show status like 'pattern%';  檢視資料庫的執行時狀態
show variables like 'pattern%';  檢視資料庫啟動時的配置資訊

1、首先需要定位執行效率有問題的SQL:

    a、執行效率有問題的SQL一般都耗時較長,業務是有感知的,從而可以幫助定位

    b、在MySQL啟動時,設定 slow_query_log 開啟慢查詢日誌   long_query_time 設定慢查詢時間閾值,這樣可以通過慢查詢日誌定位效率有問題的SQL。

2、通過 explain 分析sql的執行計劃,對於慢查詢sql主要看  possible keys 和 key ,分析索引的使用情況。

      key為null的情況,則 sql沒有走索引。

      可能原因:1)、沒有索引,需要建立 2)、存在索引,但是mysql選擇不走索引

      使用索引的可能情況:a、多列索引,查詢條件使用了 索引中最左邊的列

                                          b、like 'pattern%' 的情況   %在後面

                                          c、大文字進行搜尋,建立 全文索引, 而不是 like '%pattern%'

                                          d、如果為列 name建立索引,則  where name is null 將使用索引 

       存在索引但是不適用索引的情況:

                                          a、範圍查詢表中大部分資料時,MySQL判斷全表掃描比索引更加合適的情況下,不會使用索引

                                          b、使用  or分隔開的條件,當所有的條件列都 建立了 索引時,才會使用索引

                                          c、列型別是 字串型別,查詢時 不加 引號 就 不會使用索引(雖然會進行型別的轉換),列型別是 整數類                                                     型,查詢時 加了 引號,也會走索引

二、優化的常見方法

1、表優化   

      對  MyISAM和InnoDB型別的表來說,可以定期  分析表,檢查表,優化表

analyze table b; 分析表 使得系統得到準確的統計資訊,是的SQL能夠生成正確的執行計劃
check table b;   檢查表 檢視是否存在錯誤
optimize table b;  優化表,當表中存在動態型別(varchar text blob)時,對這些欄位頻番的更新和刪除會造成大量的空間碎片,優化表可以對錶空間碎片進行整理,減少空間的浪費

2、SQL優化

     a、優化 INSERT:同一客戶插入多條資料時,將所有的資料 組裝為一條SQL語句提交;不同客戶端插入多行,可以使用 insert delayed 語句,在對資料實時性要求不高的情況下可以使用,很快的原因在於資料並沒有真正插入檔案,而是儲存在記憶體的佇列中等待插入;可以配置資料庫,或者在建表時指定 資料目錄和索引目錄存放到不同的磁碟上,平均分佈磁碟IO,效能會有所提高;當從一個文字檔案裝載一個表時,使用 load data infile 通常比 使用很多的 insert語句快很多

     b、優化GROUP BY:預設情況下,MySQL對所有 group by d1,d2 中的 欄位進行排序,類似於 加上 order by d1,d2

explain select d2, count(d2) from b group by d2;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: b
   partitions: NULL
         type: index
possible_keys: d1
          key: d1
      key_len: 9
          ref: NULL
         rows: 7
     filtered: 100.00
        Extra: Using index; Using temporary; Using filesort
1 row in set, 1 warning (0.00 sec)

其中 Extra中的 Using filesort 即 進行了排序操作

           排序操作會帶來額外的開銷,如果 group by 的結果 對排序沒有要求,可以加上 order by null 顯示指定 不排序

     c、優化 order by 語句:某些情況下,MySQL可以使用一個索引來滿足 order by子句,而不需要額外的排序。order by使用索引的條件:where條件和 order by 使用相同的索引,並且 order by順序和 索引順序相同,並且order by 的欄位都是 升序或者降序

舉個栗子:

使用索引:
SELECT * FROM t1 ORDER BY key_part1,key_part2,... ;
SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC; 
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC;
不適用索引:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;  --order by 的欄位混合 ASC 和 DESC SELECT * FROM t1 WHERE key2=constant ORDER BY key1;  --用於查詢行的關鍵字與 ORDER BY 中所使用的不相同 
SELECT * FROM t1 ORDER BY key1, key2;  --對不同的關鍵字使用 ORDER BY

     d、優化巢狀查詢:有些情況下,可以使用 連線操作代替 巢狀查詢,連線(JOIN)更有效率的原因在於,MySQL不需要在記憶體中建立臨時表

     e、優化OR條件:為 or 的所有條件列都 建立索引,where a = 2 or  b = 2 當 a、b都有各自的獨立索引時,查詢可以使用索引,而當 a、b只有組合索引時,查詢不會走 索引。

     f、使用SQL提示:use index、ignore index、force index 來強制 使用、忽略相關索引。

3、資料庫物件的優化

     a、根據實際情況,或者在 使用一段時間之後,根據統計結果,選擇或修改欄位的型別 為 更加合適的型別和長度

     b、MyISAM型別的表,可以進行拆分提高表的訪問效率

           水平拆分:各個表的結構完全一樣,但是 儲存的資料 類別不同,按照某個欄位分類(地區,月份)。適用於 資料量很大,增長很快,並且資料可以進行分類的場合。優點在於:分割後,降低了查詢時需要讀的資料和索引的頁數,降低索引的層數,提高了查詢速度。缺點在於:增加了複雜度,查詢所有的資料需要 UNION操作;在索引關鍵字不大、資料增長速度不那麼快的情況下,水平拆分的查詢速度和 不拆分的情況下走索引的查詢速度相比,可能不會有顯著的提高,從而 水分拆分帶來的複雜度 成為了 很大的問題。

           垂直拆分:將 主鍵和一些列放在一個表中,主鍵和另外一些列放在另一個表中。可以將常用列和不常用的列分開,拆分之後,資料行變小,一個數據頁可以存放更多的資料,在查詢時就會減少I/O次數。  缺點在於 冗餘列的管理,查詢所有的資料需要 JOIN操作。

      c、逆規範化-冗餘列:在表中增加必要的冗餘列,從而降低查詢時 連線的需求。問題在於:冗餘列的更新,可以考慮 建立觸發器,來統一更新冗餘列。

      d、統計查詢的情況下,可以使用中間表提高查詢的速度。例如,統計使用者的月賬單,可以先將 當月的資料使用  insert into ...select * from... 匯入到建立的中間表中,然後在 中間表中進行統計操作。 優點:速度更快,而且可以按需建立索引和增加欄位來輔助統計操作。