高性能Mysql - 創建高性能的索引(下)(聚簇索引,覆蓋索引,全文索引)

一、聚簇索引

定義 並不是一種單獨索引類型,而是一種數據存儲方式。

聚簇索引的順序就是數據的物理存儲順序,而對非聚簇索引的索引順序與數據物理排列順序無關。舉例來說,你翻到新華字典的漢字“爬”那一頁就是P開頭的部分,這就是物理存儲順序(聚簇索引);而不用你到目錄,找到漢字“爬”所在的頁碼,然後根據頁碼找到這個字(非聚簇索引)。

具體的細節依賴於其實現方式,但InnoDB的聚簇索引實際上在用一個結構中保存了B-Tree索引和數據行。

當表有聚簇索引時,它的數據行實際上存放在索引的葉子頁中。InnoDB 將通過主鍵聚集數據,沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替,如果沒有這樣的索引,InnoDB會隱式定義一個主鍵來作爲聚簇索引。

聚簇主鍵可能對性能有幫助,也可能導致嚴重的性能問題。

聚簇的數據優點:
1. 可以把相關數據保存在一起
2. 數據訪問更快
3. 使用覆蓋索引掃描的查詢可以直接使用頁節點中的主鍵值。
缺點:
1. 如果數據全部都放在內存中,則訪問的順序就沒那麼重要了,聚簇索引也就沒什麼優勢了。
2. 插入速度嚴重依賴於插入順序
3. 更新聚簇索引列的代價很高。會強制InnoDB將每個被更新的行移動到新的位置。
4. 基於聚簇索引的表在插入新行,或者主鍵被更新導致需要移動行的時候,可能面臨“頁分裂”的問題。當行的主鍵值要求必須將這一行插入到某個已滿的頁中時,存儲引擎會將該頁分裂成兩個頁面來容納該行,這就是一次頁分裂操作,頁分裂會導致表佔用更多的磁盤空間。
5. 聚簇索引可能導致全表掃描變慢,尤其是行比較稀疏。
6. 二級索引(非聚簇索引)可能比想象彙總的要大,因爲在二級索引的葉子節點包含了引用行的主鍵列。
7. 二級索引訪問需要兩次索引查找,而不是一次。
二級索引葉子節點保存的不是指向行的物理位置的指針,而是行的主鍵值。
二級索引查找行,存儲引擎需要找到二級索引的葉子節點獲得對應的主鍵值,然後根據這個值去聚簇索引中查找到對應的行,兩次B-Tree查找。

InnoDB 和 MyISAM的數據分佈對比

MyISAM按照數據插入的順序存儲在磁盤上,因爲行是定長的,所以MyISAM可以從表的開頭跳過所需的字節找到需要的行。
而InnoDB支持聚簇索引,每一個葉子節點都包含了主鍵值,事務ID,用於事務和MVCC的回滾指針以及所有的剩餘列。
這裏寫圖片描述


在InnoDB表中按主鍵順序插入行


如果正在使用InnoDB表並且沒有什麼數據需要聚簇,那麼可以定義一個代理鍵作爲主鍵,並且設置爲AUTO_INCREMENT 自增列。這樣就可以保證數據行是按順序寫入的,對於根據主鍵做關聯操作的性能會更好。實際上很多人都是這麼幹的,但並不明白爲什麼。

最好避免隨機的(不連續且值的分佈範圍非常大)聚簇索引,特別是I/O密集型應用。

二、覆蓋索引

如果一個索引包含(覆蓋)所有需要查詢的字段的值,我們就稱之爲“覆蓋索引”。
在InnoDB如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。
哈希索引,空間索引和全文索引等都不存儲索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引。


三、全文索引

全文索引是目前搜索引擎廣泛使用的搜索技術,顧名思義,就是在全文快速匹配到具體的某個詞。

原理是先定義一個詞庫,然後在文章中查找每個詞條(term)出現的頻率和位置,把這樣的頻率和位置信息按照詞庫的順序歸納,這樣就相當於對文件建立了一個以詞庫爲目錄的索引,這樣查找某個詞的時候就能很快的定位到該詞出現的位置。

關於如果建立一個詞庫,如果是英文的話,可以根據空格來劃分,但中文就要涉及到分詞技術了。
全文索引對於模糊查詢的性能提升是非常大的。

三、總結

引用別人[姜敏(http://www.cnblogs.com/aspnet2008/)]曾經總結過的幾句話來描述一下索引的使用原則:

1:不要索引數據量不大的表,對於小表來講,表掃描的成本並不高。
2:不要設置過多的索引,在沒有聚集索引的表中,最大可以設置249個非聚集索引,過多的索引首先會帶來更大的磁盤空間,而且在數據發生修改時,對索引的維護是特別消耗性能的。
3:合理應用複合索引,有某些情況下可以考慮創建包含所有輸出列的覆蓋索引。(覆蓋索引的速度是非常快的)
4:對經常使用範圍查詢的字段,可能考慮聚集索引。
5:避免對不常用的列,邏輯性列,大字段列創建索引。

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