mysql高級_04_索引優化案例分析


  • 單表:複合索引 範圍以後的索引會失效
  • 兩個表: 左連接 索引應建在右表,右鏈接,索引在左表
  • Join
    • 儘可能減少Join 語句中 的循環總次數,永遠用小結果集驅動大結果集
    • 優先優化 內層循環
    • 保證Join語句中被驅動表上Join條件字段已經被索引
    • 當無法保證被索引且內存資源充足的前提下,不要太吝嗇JoinBuffer

避免索引失效

  • 最佳左前綴法則
    • 如果索引了多列,要遵守最左前綴法則;
    • 指的是 查詢從索引的最左前列開始並且不跳過索引中的列
  • 不要在索引列上做任何操作
    -(計算、函數(自動or手動)類型轉換) ,會導致索引失效而轉向全部表掃描
  • 存儲引擎不能使用索引中範圍條件右邊的列 (範圍之後全部失效
  • 儘量使用覆蓋索引
    • 只訪問索引的查詢(索引列於查詢列一致)
    • 減少 SELECT *
  • mysql 在使用不等於(!= 或者<>)的時候無法使用索引,會導致全表掃描
  • is null、 is not null 也無法使用索引
  • like 以通配符開頭 如(’%aaa’),索引會失效
    • 可以使用 覆蓋索引 從 ALL 升到 INDEX
  • 字符串不加單引號索引失效
  • 少用 OR 用它來連接時索引失效

在這裏插入圖片描述

2. 優化查詢


2.1 小表驅動大表

  • 永遠小表驅動大表
  • IN 和 EXISTS 的區別
  • IN 一直查找,EXISTS 遇到則立馬返回(只返回 true 或者 false, 所以 和select 後面的字段無關 ,子查詢完全可以寫成 SELECT 1 FROM t)
#如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in: 
#例如:表A(小表),表B(大表)
select * from A where cc in (select cc from B) ;//  效率低,用到了A表上cc列的索引;
select * from A where exists(select 1 from B where cc=A.cc) ;// 效率高,用到了B表上cc列的索引。 
#相反的
select * from B where cc in (select cc from A) ; //效率高,用到了B表上cc列的索引;
select * from B where exists(select 1 from A where cc=B.cc) ;//效率低,用到了A表上cc列的索引。

2.2 ORDER BY / GROUP BY

  • ORDER BY
  • ORDER BY 子句儘量使用Index方式排序,避免使用FileSort方式排序,儘可能在索引列上外城排序操作,遵照索引鍵的最佳左前綴。如果不在索引列上,FileSort有兩種算法,Mysql就要啓動雙路排序和單路排序。
  • 什麼是雙路排序和單路排序?
    • 雙路排序:Mysql4.1之前是使用雙路排序,字面的意思就是兩次掃描磁盤,最終得到數據,讀取行指針和ORDER BY列,對他們進行排序,然後掃描已經排好序的列表,按照列表中的值重新從列表中讀取對數據輸出。也就是從磁盤讀取排序字段,在buffer進行排序,再從磁盤讀取其他字段。文件的磁盤IO非常耗時的,所以在Mysql4.1之後,出現了第二種算法,就是單路排序。
    • 單路排序:從磁盤讀取查詢所需要的所有列,按照ORDER BY在buffer對它進行排序,然後掃描排序後的列表進行輸出,它的效率更快一些,避免了第二次讀取數據。並且把隨機IO變成了順序IO,但是它會使用更多的空間,因爲它把每一行都保存在了內存裏。
  • 但是,問題來了,有可能單路排序算法一次拿不出數據,那麼就還比雙路排序更消耗IO,效率更慢!
  • 提高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活動和低的處理器使用率。
  • GROUP BY的優化
  • GROUP BY實質上是先排序後進行分組,遵照索引的最佳左前綴。
  • 當無法使用索隱裂,考慮增大max_length_for_sort_data和sort_buffer_size的參數設置。
  • WHERE 高於 HAVING,能寫在WHERE限定的條件就不要去HAVING限定了。

2.3 Mysql慢查詢日誌

  • Mysql的查詢訊日誌是Mysql提供的一種日誌記錄,它用來記錄在Mysql中響應時間超過閾值的語句,具體指運行時間超過long_query_time值得SQL,則會被記錄到慢查詢日誌中。
  • long_query_time的默認爲10,意識是運行10秒以上的語句。由它來看那些SQL語句超出了我們的最大忍耐值,比如一條SQL執行超過了5秒,我們就算慢查詢,我們就可以結合Explain進行分析。
  • 默認Mysql沒有開啓慢查詢,需要我們說動設置這個參數。當然,如果不是調優需要的話,一般不建議開啓該參數,因爲開啓慢查詢日誌會或多或少帶來一定的性能影響。慢查詢日誌支持將日誌寫入文件。
  • 查看是否開啓:show global like ‘%slow_query_log%’;
  • 開啓:set global slow_query_log = 1; //設置開啓或者關閉,0爲關閉,1爲開啓
  • 具體設置時間:https://www.cnblogs.com/wt645631686/p/8321498.html

mysql提供的日誌分析工具–mysqldumpslow

  • 具體也是上面的鏈接
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章