MySQL學習筆記——索引的理解

索引的概念

  • 什麼叫索引

    索引也稱作鍵,是存儲引擎用於快速找到記錄的一種數據結構。索引可以加快查詢速度,原因是索引使用特定的數據結構(B-Tree)對特定的列額外組織存放,加快存儲引擎(索引是存儲引擎實現)查找記錄的速度。

B樹和B+樹之間的區別

  • B樹的數據結構: avatar
  • B+樹和B樹的區別

    1、有n棵子樹的結點中含有n-1個關鍵字(與B樹相同,MySQL中的B+樹索引採用這種); (此處有爭議,另一種說法是,B+樹具有n棵子樹的結點中含有n個關鍵字)

    2、所有的葉子結點中包含了全部關鍵字的信息,即所有的非葉子節點僅僅起到索引作用,非葉結點中僅含有其子樹根結點中最大關鍵字及指向該子樹的指針。(而B樹的葉子節點並沒有包括全部需要查找的信息)

    3、在B+樹上,有一個指針指向關鍵字最小的葉子節點,所有葉子節點鏈接成一個線性鏈表。(B樹不存在指針將葉子節點連成一個鏈表)

  • B樹如圖所示

avatar

  • B+樹如圖所示 avatar

索引的優點

1、索引大大減少了服務器需要掃描的數據量。

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

3、索引可以將隨機I/O變爲順序I/O。

高性能的索引策略

  • 獨立的列

    獨立的列是指索引列不能是表達式的一部分,也不能是函數的參數。例如:SELECT id FROM actor WHERE id+1=5;

    這個例子就不能使用id的索引,可以改成id=4,這就可以使用索引了。 例如另外一種常見錯誤:SELECT ... WHERE TO_DAYS(CURRENT_DATE)-TO_DAYS(date_col)<=10; 這是不能使用date_col列的索引的。

  • 前綴索引和索引選擇性

    有時候需要索引很長的的字符列,這會讓索引變得大且慢。這時就可以採用前綴索引,即只索引列的前面一部分字符,這樣可以大大節約索引空間,從而提高索引效率。但是這樣會降低索引的選擇性。索引的選擇性是指,不重複的索引值和數據表的記錄總數(#T)的比值,範圍是在1/#T到1之間。唯一索引的選擇性是1,這是最好的索引選擇性,性能也是最好的。

  • 多列索引及索引列順序

    一個常見的錯誤就是,爲每個列創建獨立的索引,或者按照錯誤的順序創建多列索引。在多個列上建立獨立的單列索引大部分情況下並不能提高MySQL的查詢性能。當出現服務器對多個索引做相交操作時(通常有多個AND條件),通常意味着需要一個包含所有列的多列索引,而不是多個獨立的單列索引。

    索引順序的選擇通常是一個令人困惑的問題,正確的順序依賴於使用該索引的查詢,並且同時需要考慮如何更好地滿足排序和分組的需求。在一個多列B+樹索引中,索引列的順序意味着索引首先按照最左列進行排序,其次是第二列,等等。選擇索引列順序有一個經驗法則:將選擇性最高的列放到索引最前列(在不需要考慮排序和分組的時候,效果很好)。

    在選擇索引的時候,既要選擇足夠長的前綴以保證較高的選擇性,同時又不能太長,以便節約空間。

聚簇索引

  • 在同一個結構中既存儲B+樹索引,又存儲數據行
  • InnoDB支持聚簇索引,也就是將數據行和相鄰的鍵值緊湊的存儲在一起,而MyISAM不支持聚簇索引,也就是將索引文件和數據文件分成兩個文件進行存儲
  • InnoDB是通過主鍵聚集數據的,不支持選擇其他索引作爲聚集索引。

聚簇索引的優點

  • 可以把相關數據保存在一起。你如實現電子郵箱時,可以根據用戶ID聚集數據。
  • 數據訪問更快。聚簇索引將索引和數據保存在同一個B+樹中,因此從聚簇索引中獲取數據比在非聚簇索引中查找更快。
  • 使用索引覆蓋掃描的查詢可以直接使用葉節點中的主鍵值。

聚簇索引的缺點

  • 聚簇索引提高了I/O密集型應用的性能,但是如果數據全部都可以放到內存中,那聚簇索引就沒有什麼優勢了。
  • 插入速度嚴重依賴插入順序,按主鍵順序插入是速度最快的。
  • 更新索引列的代價很高,因爲會強制InnoDB將每個被更新的行移動到新的位置。而行的移動有可能會導致“頁分裂”問題。當某一行必須插入到一個已滿的頁中時,存儲引擎會將該頁分裂成兩個頁面來容納該行,這就是頁分裂。
  • 聚簇索引可能會導致全表掃描變慢,尤其是行比較稀疏的時候。
  • 二級索引(非聚集索引)可能比想象的要大,因爲在二級索引的葉子節點中包含了引用行的主鍵列。
  • 二級索引訪問需要兩次查找。存儲引擎需要找到二級索引的葉子節點獲得對應的主鍵值,然後根據這個主鍵值去聚簇索引中查找對應的行。這裏進行了兩次B+樹查找。

非聚簇索引和聚簇索引之間的區別

聚簇索引是指索引文件和數據文件是同一份文件,也就是該索引實現方式中B+Tree的葉子節點上的data是數據本身,而對於B+樹或一般索引,data指的是主索引,也就是data不是數據本身,而是數據存放的地址,因此非聚簇索引比聚簇索引多一次I/O操作

MyISAM和InnoDB數據分佈

  • MyISAM和InnoDB的數據分佈其實就是聚簇索引和非聚簇索引之間的區別
  • MyISAM是非聚簇索引,而InnoDB是聚簇索引
  • InnoDB將通過主鍵聚集數據,如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引替代
  • 對於MyISAM的主鍵索引和二級索引沒有什麼區別
  • 而對於InnoDB由於它是聚簇索引,所以它的主鍵索引得到的就是整個數據行,而不是存放的對應的行號,同時,對於二級索引,存放的也不是行號,而是保存的行的主鍵值,所以需要根據這個主鍵值再進行一次索引,所以需要兩次索引查找

覆蓋索引

如果一個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之爲“覆蓋索引”。覆蓋索引能夠極大地提高性能。

覆蓋索引有許多好處: - 索引條目通常遠小於數據行大小,所以如果只需要讀取索引,那MySQL就會極大地減少數據訪問量。 - 因爲索引是按照列值順序存儲的,所以對於I/O密集型的範圍查詢會比隨機從磁盤中讀取每一行的I/O要少得多。 - 一些存儲引擎如MyISAM只在內存中緩存索引,數據則依賴於操作系統來緩存,因此要訪問數據需要一次系統調用,這會導致嚴重的性能問題。而覆蓋索引則只需要訪問內存即可。 - 由於InnoDB的聚簇索引,覆蓋索引對InnoDB特別有用。如果二級索引能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。

Note:覆蓋索引必須要存儲索引列的值,所以,MySQL只能使用B+樹做覆蓋索引。


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