Mysql查詢優化


Mysql的優化,一般是對索引優化,這里主要以innodb為主

索引是幫助MySQL高效獲取數據的排好序的數據結構,排好序是索引數據結構的特點,也是索引優化的前提。

1. 索引數據結構

索引底層使用B+樹作為其底層存儲結構。相較於二叉樹、紅黑樹、hash表、B樹而言,B+樹有自己獨特的優勢。

B+樹特點

  • 非葉子節點不存儲data,只存儲索引(冗余),可以放更多的索引
  • 葉子節點包含所有索引字段
  • 葉子節點用指針連接,提高區間訪問的性能

1.1 聚集索引(主鍵索引)

聚集索引指索引包含了完整的數據記錄,一般主鍵索引是聚集索引

mysql使用B+樹存儲索引,頁大小默認為16K,mysql在查詢時會一次性將一個頁加載到內存中(一次磁盤I/O),在內存中可以快速定位下一次需要加載的頁(有一次磁盤I/O),所以一般精准查詢只需要進行三次磁盤I/O即可找到對應的數據。

1.2聯合索引

也稱非聚集索引,非聚集索引的data存儲的是聚集索引的值,如果返回的數據包含了非索引值,那么就需要通過聚集索引找到完整的記錄,這里就會產生回表,一般建議使用覆蓋索引,也就是查詢返回值都在索引列中,例如下圖,只返回name,age,position值的話,就不需要再去聚集索引查找其他數據,速度會快很多。

2. 優化建議

  • 建表時盡量建主鍵(不建主鍵,mysql內部也會自己創建一個主鍵)
  • 主鍵盡量使用整型的自增主鍵(自增主鍵會減少插入)
  • 索引最佳實踐
    • 全值匹配
    • 最左前綴法則
    • 不在索引列上做任何操作(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描
    • 存儲引擎不能使用索引中范圍條件右邊的列
    • 盡量使用覆蓋索引(只訪問索引的查詢(索引列包含查詢列)),減少 select * 語句
    • mysql在使用不等於(!=或者<>),not in,not exists的時候無法使用索引會導致全表掃描<小於、>大於、<=、>=這些,mysql內部優化器會根據檢索比例、表大小等多個因素整體評估是否使用索引
    • is null,is not null 一般情況下也無法使用索引
    • like以通配符開頭(%abc)mysql索引失效會變成全表掃描操作
    • 字符串不加單引號索引失效
    • 少用or或in,用它查詢時,mysql不一定使用索引,mysql內部優化器會根據檢索比例、表大小等多個因素整體評估是否使用索引

3. Explain

  • 模擬優化器執行SQL語句,分析你的查詢語句或是結構的性能瓶頸
  • 如果 from 中包含子查詢,仍會執行該子查詢,將結果放入臨時表中

3.1 . id列

id列的編號是 select 的序列號,有幾個 select 就有幾個id,並且id的順序是按 select 出現的順序增長的。

id列越大執行優先級越高,id相同則從上往下執行,id為NULL最后執行

3.2 select_type列

select_type 表示對應行是簡單還是復雜的查詢

  • simple:簡單查詢。查詢不包含子查詢和union
  • primary:復雜查詢中最外層的 select
  • subquery:包含在 select 中的子查詢(不在 from 子句中)
  • derived:包含在 from 子句中的子查詢。MySQL會將結果存放在一個臨時表中,也稱為派生表
  • union:在 union 中的第二個和隨后的 select

3.3 table列

這一列表示 explain 的一行正在訪問哪個表。

當 from 子句中有子查詢時,table列是 格式,表示當前查詢依賴 id=N 的查詢,於是先執行 id=N 的查 詢。

當有 union 時,UNION RESULT 的 table 列的值為<union1,2>,1和2表示參與 union 的 select 行id

3.4 type列

關聯類型或訪問類型,即MySQL決定如何查找表中的行

依次從最優到最差分別為:system > const > eq_ref > ref > range > index > ALL 一般來說,得保證查詢達到range級別,最好達到ref

NULL:mysql能夠在優化階段分解查詢語句,在執行階段用不着再訪問表或索引。例如:在索引列中選取最小值,可 以單獨查找索引來完成,不需要在執行時訪問表

3.5 possible_keys列

查詢可能使用哪些索引來查找

出現 possible_keys 有列,而 key 顯示 NULL 的情況,這種情況是因為表中數據不多,mysql認為索引 對此查詢幫助不大,選擇了全表查詢

3.6 key列

這一列顯示mysql實際采用哪個索引來優化對該表的訪問。如果沒有使用索引,則該列是 NULL。如果想強制mysql使用或忽視possible_keys列中的索引,在查詢中使用 force index、ignore index。

3.7 key_len列

顯示mysql在索引里使用的字節數,通過這個值可以算出具體使用了索引中的哪些列

key_len計算規則如下:

  • 字符串,char(n)和varchar(n),n為字符數
    • char(n):一個數字或字母占1個字節,一個漢字占3個字節,存漢子就是3n字節
    • 如果存漢字則長度是 3n + 2 字節,加的2字節用來存儲字符串長度,因為 varchar是變長字符串
  • 數值類型:
    • tinyint:1字節
    • smallint:2字節
    • int:4字節
    • bigint:8字節
  • 時間類型
    • date:3字節
    • timestamp:4字節
    • datetime:8字節
  • 如果字段允許為 NULL,需要1字節記錄是否為 NULL
  • 索引最大長度是768字節,當字符串過長時,mysql會做一個類似左前綴索引的處理,將前半部分的字符提取出來做索 引。

3.8 ref列

這一列顯示了在key列記錄的索引中,表查找值所用到的列或常量,常見的有:const(常量),字段名

3. 9rows列

是mysql估計要讀取並檢測的行數,注意這個不是結果集里的行數

3.10 Extra列

這一列展示的是額外信息


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM