天天看點

面試必備——mysql之索引mysql之索引

mysql之索引

建立好的索引能加快查詢速度,不建立索引查詢時會全文查找,找所有的行找完後才會傳回 。但是索引會影響更新;插入的速度。是以要合理的建立索引。

注:對于innoDB引擎而言索引結構隻有hash與b+樹而MyISAM引擎支援空間資料索引(R-Tree),可以用于地理資料存儲。空間資料索引會從所有次元來索引資料可以有效地使用任意次元來進行組合查詢,本文不做具體介紹。

語句:

#單列索引(每個索引隻包含一列)length是建立的字首索引,節省空間
--建表時
index indexName(col_name(length))
--建表後
create index indexName on TableName(col_name(length))
#組合索引(遵循最左比對原則,即在查詢條件中使用了第一個字段索引才會使用)
create index index_name on table_name(col_name1,col_name2,...);
#唯一索引(值必須唯一,允許一個空值  ps:主鍵索引是一種特殊的唯一索引,不允許有空值)
CREATE UNIQUE INDEX index_name ON table_name(col_name...)
#全文索引(FULLTEXT 5.6後支援innodb引擎,之前隻支援MyISAM)
#全文索引用來查找文本中的關鍵字,不是直接與索引的值比較
CREATE FULLTEXT INDEX index_fulltext_content ON table_name(col_name)
#FULLTEXT更像一個搜尋引擎,與match against操作(全文搜尋模式)并且隻支援英文
#MySQL 全文搜尋隻是一個臨時方案,對于全文搜尋場景,更專業的做法是使用全文搜尋引擎,例如 ElasticSearch 或 #Solr。
 	
           

可以使用如下語句檢視表中的索引

show INDEX from mytable
           

如圖:

面試必備——mysql之索引mysql之索引

哈希索引

哈希索引是通過關鍵碼值(k,v)進行資料通路的資料結構,k值是索引列,v是通過hash函數計算出來的指向Page 頁面的chain指針,下圖展示了name查找的過程。

面試必備——mysql之索引mysql之索引

但是不同的key可能會的到相同的value,進而發生hash碰撞,innodb中采用拉鍊法來解決沖突。

優點:雜湊演算法的時間複雜度為O(1),查找隻需要計算一次,對于等值查找速度非常快。

缺點:不支援範圍查找,不支援排序。

自适應哈希索引

通過哈希索引的方式實作,由innodb自動根據經常使用的列建立,不能人為幹預。可以通過SHOW ENGING INNODB STATUS檢視使用情況,預設是開啟的通過innodb_adaptive_hash_index來禁用/啟動。

B+樹索引

B+樹是為磁盤或其他輔助而存取輔助裝置設計的一種平衡查找樹,由B樹和索引順序範文的方法演化而來。

如圖一個高度為2的B+樹:

面試必備——mysql之索引mysql之索引

B+樹的葉子節點用來存放資料,而葉子結點的每個頁首位相連維護成一個有序的雙向循環連結清單每個頁中的紀錄組成一個單向連結清單。非葉子節點中存放的是索引(位址),對于單個節點有限的情況下也能存放大量索引,是以可以很好的降低樹的高度,減少IO次數,進而加快查詢。

資料結構:

在b+樹中一個節點的key從左到右遞增排列,并且如果某指針左右相鄰的key的左右兩個節點分别是keyn-1,keyn+1,那麼該指針指向節點的所有key大于等于keyn-1,小于等于keyn+1

面試必備——mysql之索引mysql之索引

查找過程:

先從根節點開始進行二分查找,找到一個key所在的指針,遞歸的在指針指向的節點查找,知道找到所在的葉子節點,如果該索引為聚集索引可以通過頁中的頁目錄進行二分查找找到對應的槽找到相應的data,如果是輔助索引那麼找到葉節點後周遊葉節點這個單連結清單直到找到data。

因為插入和删除會破壞平衡性,是以在插入和删除之後,需要對其進行分裂;合并;旋轉等操作來維持平衡性這是非常耗時的是以在插入和删除多的列不要建索引。

磁盤預讀:磁盤每次讀取都會預讀,會提前将連續的資料讀入記憶體中,這樣就避免了多次 IO,而B+樹節點預設是一頁16kb,是以每一頁隻有一次IO讀。

聚集索引

存放表中所有行記錄的資料的一顆B+樹,每一張表中隻有一個。一般mysql會通過主鍵自動建立聚集索引,如果沒有主鍵自動用唯一非空列,唯一鍵沒有,mysql會建一個6個位元組rowid隐藏字段來作為聚集索引。查詢優化器傾向于走聚集索引,由于B+樹索引是有序的在使用order by,group by語句并不會對其進行排序和分組。

輔助索引

也叫二級索引,也就是我們手動建立的索引,葉子節點中隻有建立索引指定的那一列資料和一個指向聚集索引行資料的書簽。

如:在字段name上建立一個索引,如果要執行

select * from test where name='zzh'

首先會通過name上的索引找的zzh,再找到頁面紀錄的書簽然後從聚集索引中找到所需的資料,這種從輔助索引找的聚集索引的過程叫做回表,我們應該避免這種情況,可以通過覆寫索引來避免。

覆寫索引

從輔助索引中可以得到查詢的紀錄,而不需要去找聚集索引,因為輔助索引中不包含整行記錄,遠遠小于聚集索引,可以減少大量的IO操作。

實作:将被查詢的字段建立到聯合索引中去。

索引的優化

  1. 獨立的列:在查詢中索引列不能用于計算;函數參數。
  2. 多列索引:有多個列作為查詢條件時,一個多列索引比多個單列索引性能更高。
  3. 順序:讓選擇性高的列放前面,區分度的公式是 COUNT(DISTINCT col)/COUNT(*)。表示字段不重複的比率,比率越大我們掃描的記錄數就越少。
  4. 最左字首比對:MySQL會一直向右比對直到遇到範圍查詢 (>,<,BETWEEN,LIKE)就停止比對。
  5. 盡可能的擴充索引,不要建立立索引。比如表中已經有了a的索引,現在要加(a,b)的索引,那麼隻需要修改原來的索引即可。
  6. 避免回表,覆寫索引。
  7. 字首索引:對于 BLOB、TEXT 和 VARCHAR 類型的列,必須使用字首索引,隻索引開始的部分字元。

索引使用條件

  1. 對于中大型的表,200多行資料以上。
  2. 列中的資料區分度要高(不重複)
  3. 删除和插入比較少的列
  4. 特大型的表,建立和維護索引的代價将會随之增長。這種情況下,需要用到一種技術可以直接區分出

    需要查詢的一組資料,而不是一條記錄一條記錄地比對,例如可以使用分區技術。

優點

  1. 大大減少了伺服器需要掃描的資料行數。
  2. 幫助伺服器避免進行排序和分組,是以會避免建立臨時表加快查找速度
  3. 将随機 I/O 變為順序 I/O(B+Tree 索引是有序的,會将相鄰的資料都存儲在一起)。

思路文獻參考:

《MySQL實戰》

《高性能MySQL》