MYSQL學習(三) --索引詳解


 創建高性能索引

(一)索引簡介

  1. 索引的定義

  索引,在數據結構的查找那部分知識中有專門的定義。就是把關鍵字和它對應的記錄關聯起來的過程。索引由若干個索引項組成。每個索引項至少包含兩部分內容。關鍵字和關鍵字對應記錄在存儲器位置信息。索引是組織磁盤文件的一種重要的技術。

數據庫的數據量通常比較大,都是存儲在磁盤上。通過存儲引擎對磁盤文件的數據進行管理。而索引是存儲引擎御用快速找到記錄的一種數據結構。

  2.索引的優點

  (1)大大減少服務器需要掃描的數據量

  (2)索引可以幫助服務器避免排序和臨時表

  (3)索引可以將隨機IO轉換成順序IO

  3.索引三星系統原則

  (1)第一星:索引將相關的記錄放在一起。即在一系列必要的列上建立索引,不必為where條件里的所有得列建立索引。

  (2)第二星:索引中數據的順序和排序要求的數據的順序一致。通常將選擇性更高的列放在索引列的最前面。

  (3)第三星:索引中的列包含查詢所需要的所有列。因為索引中已經包含查詢所需的全部字段,所以不需要在進行行查詢(覆蓋索引的定義)。

(二)索引類型

  其中,索引是在存儲引擎層實現的。因此,不同的執行引擎,自己選擇使用實現自己的索引類型。

  1.B-Tree 索引

  (1)B+樹數據結構

 

  B+樹的定義是在B樹的基礎之上定義的。相比B+樹,區別部分有兩點。

  A.非葉子結點只存key,不存儲指向數據的指針(ROWID)

  B.葉子結點都保存一個指向相鄰節點的指針。

  區別A.非葉子節點不存儲ROWID,索引項更小。一塊可以存儲更多的索引項。所以,可以存儲更多的非葉子索引項。一個索引項能定位更多的葉子結點。

  區別B.葉子節點根據指針鏈接,范圍查詢非常簡單(如果是B樹結構的話,范圍查找需要 葉子節點和內部結點之間不停的往返)。

 

  (2)使用B+樹索引的存儲引擎

  InnoDBMyISAM

  B+樹索引是邏輯結構是B+樹、物理存儲結構是鏈式存儲

  (3)B+樹索引適合的查詢類型

  1. 鍵值范圍
  2. 鍵前綴查找(只使用最左前綴查找)
  3. 只訪問索引的查詢(覆蓋索引)
  4. 全鍵值

  其實是覆蓋索引。即索引中的字段能覆蓋查詢語句中的全部字段(包括分組、排序字段)。

 

  2. 哈希索引

  哈希索引是線性索引。是基於哈希表實現。只有精確匹配索引的所有列的查詢才有效。

  哈希索引存儲在哈希表中。邏輯結構是線性表,物理存儲結構是順序存儲。

  不同的key通過哈希函數計算,可能產生相同的結果。即沖突。哈希索引用的沖突解決算法是鏈地址法(索引相同的記錄指針放在一個鏈表中)

  索引表是線性表的順序存儲。存儲在連續的存儲空間中。

  (1).哈希索引的索引項包含哈希值行指針

   哈希值:由索引列按照哈希函數計算,獲得的哈希值。

   行指針:當前哈希值對應的行的指針

  (2).哈希索引特點

  1. 哈希索引只包含哈希值和行指針。不包含其它列信息。因此,無法避免讀取行(無法實現覆蓋索引)
  2. 哈希索引的索引項不是按照索引值順序存儲的。所以,無法避免排序
  3. 哈希索引不支持索引列的匹配查找。

  3. 全文索引

  全文索引和哈希索引一樣,也是一種線程索引。本質是倒序索引。

  4.B+樹索引和哈希索引的區別

  1. 哈希索引的特殊性,索引的檢索可以一次定位。而B樹索引的檢索需要工根節點到樹枝結點,最后再到葉子結節點。這樣多次IO訪問。所以,哈希索引的效率遠高於B樹索引。
  2. 哈希索引無法避免排序(按照哈希碼順序存儲的,不是按照索引列進行順序存儲的)。B樹索引在特殊情況下是可以避免排序操作的(索引列作為索引key)。
  3. 哈希索引只能使用全部索引鍵來查詢,不能用部分索引鍵來查詢。(哈希函數是一種對應關系,所以,必須要所有的參數才能得到哈希碼,部分索引建是不可以的)

(三)高性能索引策略

  1.獨立的列

  索引列不能是表達式,也不能是函數。

  例如:SELECT actor_id FROM actor WHERE actor_id+1=5  這種寫法,就算在actor_id上建立了索引,也不起效。索引列actor_id需要是獨立的列才可以。

  2.多列索引

  多列索引也叫符合索引。即同時對多個列建立索引。比如(A,B,C)。

  (1). 需要使用多列索引的場景

  1. 服務器需要對多個索引進行相交運算(通常是AND條件)。
  2. 服務器需要對多個索引進行聯合操作(通常是OR條件)。

  (2).多列索引的生效規則

  比如(a,b,c),a,b,c都是排好序的。在任何一段a的下面b都是排好序的。在任何一段b的下面c都是排好序的。多列索引生效原則是從前向后依次生效。如果中間索引列沒有起作用,則該索引列之前的索引列起作用。

  例如 (1)select * from mytable where a=3 and b>7 and c=3;  --a用到了,b也用到了,c沒有用到,這個地方b是范圍值,也算斷點,只不過自身用到了索引

  3.聚簇索引

  聚簇索引:不是一種索引類型,是一種數據存儲方式

  InnoDB的聚簇索引,在同一個結構中保存了B-Tree索引和數據行。

  當表有聚簇索引的時候,它的數據實際上是存儲在索引的葉子頁(leaf page)中。數據只有一份,所以,一個表只有一個聚簇索引。聚簇是指鍵值相鄰的數據行緊簇的保存在一起。

  聚簇索引的葉子節點也是數據節點。而非聚簇索引的葉子結點仍然是索引節點。只不過,它有指向對應數據塊的指針。

  (1).聚簇索引和二級索引

  1. 聚簇索引的定義

  在InnoDB中,聚簇索引就是主鍵索引。如果表中沒有定義主鍵,則InnoDB選擇一個唯一的非空索引作為主鍵。如果沒有這樣的索引,InnoDB會隱式的定義一個主鍵來做聚簇索引。

  2.聚簇索引特征

  數據存儲和索引放在一起,找到索引,就找到數據。

  由於聚簇索引是將數據跟索引結構放到一塊,因此一個表僅有

  二級索引定義

  非主鍵索引就是二級索引。

  二級索引特征

  將數據存儲和索引存儲分開的結構,索引結構的葉子節點指向數據的對應行。

  在InnoDB存儲引擎中,在聚簇索引之上創建的索引稱之為輔助索引。即二級索引。輔助索引總是需要二次查找的。輔助索引葉子結點存儲的不是行的物理位置,而是主鍵值。(然后根據主鍵值去聚簇索引中查詢數據)

  (2).MyISAMInnoDB的主鍵索引、二級索引對照圖

 

 

 

 

 

 

 

 

  熟悉兩種引擎的數據和索引分布,就真正理解了MYSQL的存儲和索引查詢。

  1. MyISAM數據分布

如上圖所示,MyISAM的數據和索引分開儲存的。MyISAM是按照插入的順序,順序的存儲在磁盤上。類似數組那樣順序存儲。

   2. MyISAM索引

它對應的不論主鍵索引還是二級索引,都是典型的B+樹索引形式。葉子結點對應的是行指針(行在磁盤中的具體位置)

  3. InnoDB數據分布

如上圖所示,InnoDB支持聚簇索引。其中,聚簇索引就是數據。在聚簇索引的葉子節點上,除了主鍵外,還有事務ID,回滾指針和其余非主鍵字段。所以,通過主鍵索引可以直接找到數據.

  4. InnoDB主鍵索引

InnoDB的主鍵索引和數據分布內容一樣。主鍵索引就是其數據分布。

  5.InnoDB二級索引

  二級索引也是標准的B樹索引。只是葉子結點指的不是行指針,而是主鍵值。所以,整個葉子結點的索引項是[key+主鍵]。

  6. 聚簇索引的選擇和重建

  聚簇索引默認是按照主鍵建立的主鍵索引。如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引替代。

  InnoDB的數據插入是按照主鍵順序插入行的

  4.覆蓋索引

  如果一個索引包含(或者說覆蓋)查詢的所有字段(查詢字段和where條件字段)的值,我們稱之為覆蓋索引。【由此可見,覆蓋索引是索引的一個分類而已】

  覆蓋索引效率高的幾個原因

  1. 覆蓋索引,只需要查找索引,不需要二次查找數據行。少一次操作。
  2. 覆蓋索引是按照索引字段順序存儲。因而,支持范圍查找。

  5.使用索引掃描來排序

  核心思路是:因為索引是有序的。如果排序要求的順序和索引的順序一致,就可以直接使用索引的順序。從而減少對排序的操作

  ORDER BY和查找型查詢的限制是一樣的:需要滿足索引的最左前綴原則,否則,MySQL無法使用索引排序。但有一個特殊情況:就是前導列為常量。例如,有一個索引為(A,B,C),那么這樣的SQL語句也會用索引排序。

  select id from table where A=2 order by B,C;

  第一個索引列A為常量22后面對應的BC也是有序的。所以,這個查出的數據是有序的。

  select id from table where A>2 order by B,C; 這個不可以。

(四)維護索引和表

  索引如此重要,所以需要對索引和表進行實時維護。確保索引正常工作。

  1.找到並修復損壞的表

  檢查:通過CHECK TABLE來檢查引擎是否發生表損壞。

  維修:使用 ALTER TABLE innoDB_tbl ENGINE = INNODB;

  2.更新索引統計信息

  ANALYZE TABLE

  3.減少索引和數據碎片

  數據存儲的碎片有

  (1).行碎片

  數據行被存在多個地方的多個片段中。

  (2).行間碎片

  邏輯上順序的也,或者行在磁盤上不是順序存儲的。行間碎片對全表掃描和聚簇索引掃描影響較大。

  (3).剩余空間碎片

  數據頁中有大量的剩余空間。從而導致服務器讀取大量不需要的數據。

 

  修復: OPTIMIZE TABLE ;或者 ALTER TABLE innoDB_tbl ENGINE= <engine>;

(五)為什么 絕大多數索引選擇B+樹?

  MYSQL查詢的本質是在一個數據集合中的查找數據。查找常見方式以及場景如下

  1.順序查找,場景:無序,數據量較小。

  2.折半(二分)查找,場景:順序線性表存儲。數據量較小。

  3.二叉樹查找(AVL):場景:二叉樹或者平衡二叉樹存儲(有序鏈式存儲),數據量中等或者較小。

  4.多路查找樹(B樹或B+):場景:B+樹存儲(有序存儲),可以處理數據量很大的數據。

因為B樹存儲可以讓樹的階(深度)控制在較小的分為內。階(深度)每少一層,查詢就會少一次索引的獲取。因而,B樹這個類型的存儲是MYSQL選擇索引數據結構的一個很好的方案。

  為什么選擇B+樹而不是B

  1. B+樹非葉子結點不存數據,所以,可以存儲更多的結點,因而,樹的階就越小。從樹形上來看越矮胖。可以較少IO操作。
  2. 葉子結點都添加一個指向相鄰葉子的指針。范圍掃描更容易。


免責聲明!

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



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