[MySQL] 索引學習筆記

1. 索引分類

  • 單值索引: 一個索引只包含單個列, 一個表可以有多個單列索引, 單值索引一次查詢只能用一個
  • 唯一索引: 索引列的值必須唯一, 但允許有空值
  • 複合索引: 一個索引包含多個列

2. 索引創建/刪除

  • 創建: CREATE [UNIQUE] INDEX idx_mytable_colname ON mytable(colname(length))
  • 添加: ALTER mytable ADD [UNIQUE] INDEX idx_mytable_colname ON (colname(length))
  • 刪除: DROP INDEX [idx_mytable_colname] ON mytable
  • 查看: SHOW INDEX FROM mytable

3. 四種添加索引的方式

  • 添加一個主鍵, 也就是說添加一個不能爲空的唯一索引
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list)
  • 創建可以有空值的唯一索引
ALTER TABLE tbl_name ADD UNIQUE index_name(column_list)
  • 添加普通索引, 索引值可出現多次
ALTER TABLE tbl_name ADD INDEX index_name(column_list)
  • 創建全文索引
ALTER TABLE tbl_name ADD FULLTEXT index_name(column_list)

4. 索引結構

  • BTree索引
  • Hash索引
  • full-text全文索引
  • R-Tree索引

5. 需要創建索引的情況

  • 頻繁作爲查詢條件的字段應該創建索引
  • 查詢中與其它表關聯的字段, 外鍵關係建立索引
  • 高併發下傾向創建組合索引
  • 經常排序的字段最好建索引
  • 查詢中統計或者分組的字段建索引

6. 不應建索引的情況

  • 頻繁更新的字段
  • where條件裏用不到的字段
  • 包含很多重複內容且分佈均勻的字段
  • 表記錄很少的情況

7. MySQL常見瓶頸

  • 語句有問題
  • CPU: CPU飽和, 一般發生在數據裝入內存或從磁盤上讀取數據的時候
  • IO: IO瓶頸發生在裝入數據遠大於內存容量的時候
  • 服務器硬件瓶頸: top, free, iostat, vmstat 等查看系統性能

8. Explain 解析

  • 顯示內容:
    • 表的讀取順序
    • 數據讀取操作的操作類型
    • 哪些索引可以使用
    • 哪些索引被使用
    • 表之間的引用
    • 每張表有多少行被優化器查詢
  • 返回結果包含字段
    • id select 查詢的系列號, 包含一組數字, 表示查詢中執行select子句或操作表的順序
      三種情況:
      - id相同, 執行順序由上至下
      - id全不同, id越大優先級越高,越先執行
      - id部分相同, 優先執行跟順序執行並存
    • select_type 查詢的類型, 主要用於區分普通查詢/聯合查詢/子查詢等複雜查詢
      六種返回結果:
      - SIMPLE 簡單的select查詢, 不包含子查詢或UNION
      - PRIMARY 查詢中若包含任何複雜子部分, 表示最外層查詢
      - SUBQUERY 在select或where列表中包含子查詢
      - DERIVED 在from列表中包含的子查詢被標記爲DERIVED, MySQL會遞歸執行這些子查詢, 把結果放在臨時表中
      - UNION 若第二個select出現在UNION之後, 則被標記爲UNION, 若UNION包含在FROM子句的子查詢中, 外層select被標記爲DERIVED
      - UNION RESULT 從UNION表獲取結果的select
    • table 表名
    • type 訪問類型, 顯示查詢使用了何種類型,
      最好到最差依次是: system>const>eq_ref>ref>range>index>ALL
      - system 表只有一行數據(等於系統表), 是const類型的特例, 平時不會出現
      - const 表示通過一次索引就找到了, 用於比較primary key或者unique索引. 因爲只匹配一行數據, 所以很快, 如將主鍵置於where列表, MySQL就能將該查詢轉換爲一個常量
      - eq_ref 唯一性索引掃描, 對於每個索引鍵, 表中只有一條記錄與之匹配. 常見於主鍵或者唯一索引掃描
      - ref 非唯一索引掃描, 返回匹配某個單獨值的所有行. 本質上也是一種索引訪問, 屬於查找和掃描的混合體
      - range 只檢索給定範圍的行, 使用一個索引來選擇行.
      - index 只遍歷索引
      - ALL 全表掃描
    • possible_keys 系統推測可能應用在這張表中的索引, 不一定被實際使用
    • key 實際使用的索引, 如果爲NULL, 表示沒有使用索引, 查詢中若使用了覆蓋索引, 則該索引僅出現在key列表中
      覆蓋索引是指創建與使用的聯合索引剛好完全一致
    • key_len 表示索引中使用的最大可能字節數, 時根據表定義計算得到的, 不是表內檢索出的, 在不損失精度的情況下, 長度越短越好
    • ref 顯示索引的哪一列被使用, 是一個常數
    • rows 顯示每張表有多少行被優化器查詢過
    • Extra - Using filesort 文件排序 說明MySQL不是按照表內索引順序讀取, 而是使用了一個外部索引排序, 這是比較危險的情況
      - Using temporary 對查詢結果排序時使用了臨時表保存結果, 常見於order by和group by, 使用group by時一定要保證字段與索引順序一致
      - Using index 表示使用了覆蓋索引, 如果同時出現using where表明索引被用來執行索引鍵值的查找, 如果沒有出現using where表明索引被用來讀取數據而非執行查找動作. 覆蓋索引是指, select的字段剛好跟建索引的字段一樣且順序一致, 換句話說, 查詢列被所建索引覆蓋, 所需數據直接從索引中獲取即可
      - Using where 表明使用了where搜索
      - Using join buffer 使用了連接緩存, 這是可以把join緩存區調大
      - impossible where where語句返回false
      - select tables optimized away 在沒有group by子句的情況下, 基於索引優化min/max操作
      - distinct

9. 索引優化需要注意問題:

  • 如果對範圍查詢的字段使用索引, 其後的索引將失效
  • 建組合索引時, 要保證索引順序與字段的使用順序一致, 否則索引可能失效, 對於orderby字段,失效的標誌是extra中顯示Using filesort
  • 要想覆蓋索引生效, 一定不能使用select *來取數, 而是要從索引列取數
  • 兩表關聯時, 左連接的話要在右表建索引, 右連接在左表建索引
  • join 優化時要注意: 1.使用小表驅動大表, 2.優先優化內層循環, 3.保證join語句中被驅動表上join字段已經被索引, 4.調整joinbuffer大小
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章