【MySQL】如何理解索引?

索引概述

什麼是索引?

在數據之外,DB還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用數據,在這個數據結構的基礎上可以實現高級查找算法,它們就是索引。索引是幫助MySQL高效獲取數據的數據結構。

當數據量很大的時候,索引對性能的影響很大。當數據量很小,負載很低的時候,不恰當的索引可能對性能的影響不明顯,但是如果數據量很大,性能會急劇下降。

一般來說索引本身也很大,不可能全部存在內存中,因此索引往往以索引文件的形式存儲在磁盤上。如果沒有指明,一般索引都是指B樹(多路搜索樹,不一定是二叉的)結構的索引。其中聚集索引、次要索引、複合索引、前綴索引、唯一索引默認都是使用B+樹索引,統稱索引。除了B+樹索引還有哈希索引等。

索引的工作過程是什麼樣的?

示例:select * from emp where emp_id=1;如果emp_id有索引,則會使用索引找到emp_id爲1的行。也就是MySQL先在索引上按值查找,然後返回所有包含該值的數據行。

優勢V.S.劣勢

  • 優勢:是提高檢索的效率,降低數據庫的IO成本。通過索引對數據進行排列,降低數據排序的成本,降低CPU的消耗。
  • 劣勢:實際上索引也是一張表,保存了主鍵和索引字段,並指向實體表的記錄,所以索引列也是要佔空間的。雖然索引大大提高了查詢速度,同時會降低更新表的速度。因爲更新表還需要更新索引信息。索引只是提高效率的一個因素,對於大數據量的表,需要花時間研究簡歷優質的索引,才能實現真正的優化查詢。

索引的分類

  • 單值索引:一個索引只有一個列,一個表可以有多個單值索引
  • 唯一索引:索引列的值必須唯一,但允許有空值
  • 複合索引:一個索引有多個列。

基本語法

  • 創建1:CREATE [UNIQUE] INDEX indexname ON table(columnname(length));
  • 創建2:ALTER table ADD [UNIQUE] INDEX[indexname] ON (columname(length));
  • 刪除:DROP INDEX [indexname] ON table;
  • 查看:SHOW INDEX FROM table

添加索引的四種方式:

  • ALTER TABLE tablename ADD PRIMARY KEY(columnname):添加一個主鍵,索引值必須唯一,且不能爲空。
  • ALTER TABLE tablename ADD UNIQUE indexname(columname):創建唯一索引,可以有多個null值。
  • ALTER TABLE tablename ADD INDEX indexname(columnname):添加普通索引,索引值可以出現多次。
  • ALTER TABLE tablename ADD FULLTEXT indexname(columnname):指定了索引爲全文索引。

MySQL的索引結構

  • B樹索引:B樹通常意味着所有的值都是按順序存儲的,且每個葉子頁到根的距離相同。B樹索引能夠加快訪問數據的速度,因爲存儲引擎不需要全表掃描來獲取需要的數據,而是從索引的根節點開始搜索。根節點的槽種存放了指向子節點的指針,存儲引擎根據這些指針向下查找。通過比較節點頁的值和要查找的值來找到適合的指針,進入下層子節點。這些指針定義了子節點頁種值的上限和下限,最終存儲引擎要麼找到了對應的值,要麼記錄不存在。
  • 哈希索引
  • 全文索引
  • R樹索引

什麼時候需要創建索引?

  • 主鍵自動建立唯一索引
  • 頻繁作爲查詢條件的字段
  • 查詢種與其他表關聯的字段,外鍵關係建立索引
  • 高併發一般傾向於創建組合索引
  • 查詢中排序的字段(排序字段如果用索引去查會提高排序的速度)
  • 查詢中統計或者分組的字段。

什麼時候不要創建索引?

  • 表中記錄很少
  • 頻繁更新的字段不適合創建索引
  • Where條件中用不到的字段不創建索引
  • 數據重複且分佈平均的字段。如果數據列有很多重複項,建立索引沒有太大效果

索引的選擇性是指索引列中不同值的數與表總數的比。索引的選擇性越接近於1,索引的效率越高。

性能分析

MySQL中有專門優化select語句的優化器模塊,可以通過計算分析系統收集到的統計信息,爲Qurey提供其認爲最優的執行計劃。

當MySQL得到一條Qurey請求,命令解析器模塊會完成請求的分類,區分出是select語句並轉發給MySQL Query Optimizer,優化器會先對整條語句進行優化,處理掉常量表達式的預算,換算成常量值,並對查詢條件進行簡化和轉換,去掉一些無用或顯而易見的條件,調整結構。然後分析Qurey的Hint信息,看顯式Hint信息能否完全確定Quurey的執行計劃。如果沒有Hint或者信息不足完成,則會讀取涉及對象的統計信息,根據Qurey進行相應的計算分析,然後得出最後的執行計劃。

MySQL的常見瓶頸:

  • CPU:一般在數據裝入內存或從磁盤讀取的時候可能會發生CPU飽和
  • IO:在裝入數去大於內存容量的時候會發生磁盤IO瓶頸
  • 服務器硬件的性能:可以通過top、free、iostat、vmstat來查看

EXPLAIN關鍵字

查看執行計劃:使用EXPLAIN關鍵字可以模擬優化器執行SQL查詢語句,從而直到MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸。

 

 執行計劃包含的信息:上圖表頭的字段

  • id是select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序。id相同表示執行順序由上到下。如果是子查詢,id的序號會遞增,id越大的優先執行。
  • select_type:查詢的類型,主要用於區別普通查詢、聯合查詢、子查詢等複雜查詢。
    • SIMPLE:簡單的select查詢,不包含子查詢或者union
    • PRIMARY:查詢中如果包含任何複雜的子部分,最外層查詢則被標記爲PRIMARY
    • SUBQUERY:select或where中的子查詢
    • DERIVED:在from列表中包含的子查詢會被標記爲DRIVED,MySQL會遞歸執行這些子查詢,把結果放在臨時表裏。
    • UNION:若第二個SELECT出現在UNION之後,則被標記爲UNION。若UNION包含在FROM子句的子查詢中,外層的SELECT將被標記爲DERIVED。
    • UNION_RESULT:從UNION表中獲取結果的select
  • type:顯式查詢使用了何種類型,從最好到最差:SYSTEM>CONST>EQ_REF>REF>RANGE>INDEX>ALL。一般要保證查詢至少達到range級別,最好達到ref級別。
    • SYSTEM:表只有一行記錄(等於系統表),是CONST類型的特例,平時不會出現
    • CONST:表示通過索引一次就找到了,CONST用於比較primary key或者unique索引。因爲只匹配一行數據,所以很快。如果將主鍵置於where列表,MySQL就能將該查詢轉換爲一個常量。
    • EQ_REF:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配,常見於主鍵或唯一索引掃描。
    • REF:非唯一性索引掃描,返回匹配某個單獨值的所有行,本質也是索引訪問,返回匹配某個單獨值的行,可能找到多個行,屬於查找和掃描的混合體。
    • RANGE:只檢索給風範圍的行,使用一個索引來選擇行,key列顯式使用了哪個索引,一般是where語句中出現了between、<、>、in等查詢。只用掃描部分索引。
    • INDEX:只遍歷索引樹,快於ALL,因爲索引文件通常比數據文件小,也就是說雖然all和index都是讀全表,但是index是從索引中讀取,而all是從硬盤讀取。
    • ALL:遍歷全表找到匹配行。
  • possible_keys:顯示可能應用在這張表中的索引,一個或多個,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用。
  • key:實際使用的索引,如果是null,則沒有使用索引。如果查詢中出現了覆蓋索引,則索引只出現在key表中。(查詢的字段和索引字段完全匹配)
  • key_len:表示索引中使用的字節數,可查詢中使用的索引的長度。在不損失精度的情況下,長度越短越好。顯示的是最大可能長度而不是實際使用長度。根據表定義計算得到,而不是表內檢索出來的
  • ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查找索引列上的值
  • rows:根據表統計信息及索引選用情況,大致估算出找到所需記錄所需讀取的行數。
  • extra:包含不適合在其他列顯示但很重要的信息
    • Using filesort:說明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取,mysql無法利用索引完成的排序操作叫做文件排序【需要優化】
    • Using temporary:使用臨時表保存中間結果,MySQL在對查詢結果排序的時候使用臨時表,常見於orderby和groupby。
    • Using index:標識select操作使用了覆蓋索引(select的數據列只用從索引中就能取得,不必讀取數據行,MySQL可以利用索引返回select列表中的字段,不必根據索引再次讀取數據文件,查詢列被所建的索引覆蓋),避免訪問表的數據行,如果同時出現using where表明索引被用來執行索引鍵值的查找。
    • Using where
    • Using index

 

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