聚集索引和非聚集索引的理解

首先理解一下什麼是聚集索引什麼是非聚集索引?

我們先看看百度百科對聚集索引的定義:

天吶,這是什麼??

新技術人被英語差、技術又菜的前輩的可怕翻譯迫害,想想都是一件可怕的事。


我們看個正常的定義:

A clustered index is a special type of index that reorders the way records in the table are physically stored. Therefore table can have only one clustered index. The leaf nodes of a clustered index contain the data pages.

A nonclustered index is a special type of index in which the logical order of the index does not match the physical stored order of the rows on disk. The leaf node of a nonclustered index does not consist of the data pages. Instead, the leaf nodes contain index rows.

其實很簡單,我們的sql數據庫是行數據庫,數據是一行一行存儲的,而聚集索引是個特殊的索引,相當於這一行行記錄的物理編號,描述這一行行數據的物理存儲順序。所以,一張表只會有一個聚集索引。

如圖,聚集索引的葉子節點指向的就是實際數據頁,兩個相鄰的聚集索引1和2,它們指向數據塊上的位置——張三和李四,也得給我住兩隔壁。

拿mysql來說,聚集索引通常是表的主鍵若無主鍵則爲表中第一個非空的唯一索引,還是沒有就採用innodb存儲引擎爲每行數據內置的ROWID作爲聚集索引(隱藏索引)

 

再來,不是聚集索引的就是非聚集索引,兩個相鄰排排站的非聚集索引,它們實際指向的數據可能隔了十萬八千里。天吶,其實它就是二級索引啊。

舉個例子吧:

create table people (
`id` INT UNSIGNED AUTO_INCREMENT,
`name` VARCHAR(20),
PRIMARY KEY(`id`),
KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

該表主鍵id就是該表的聚集索引,name就是非聚集索引;表中每行數據都是按id排序存儲的;

比如要查找名字是'Aa'和'Ab'這兩個人,他們在name索引表中的位置可能是相鄰的,但實際的存儲位置則不然。

通過name索引最終只能查出數據的主鍵,然後再按主鍵撈出來。

聚集索引只能有一個,非聚集索引可以有多個。

那麼爲什麼重複率高的字段不適合作爲索引

理論文章會告訴你值重複率高的字段不適合建索引。不要說性別字段只有兩個值,網友親測,一個字段使用拼音首字母做值,共有26種可能,加上索引後,百萬加的數據量,使用索引的速度比不使用索引要慢!

一個表可能會涉及兩個數據結構(文件),一個是表本身,存放表中的數據,另一個是索引。索引是什麼?它就是把一個或幾個字段(組合索引)按規律排列起來,再附上該字段所在行數據的物理地址(位於表中)。比如我們有個字段是年齡,如果要選取某個年齡段的所有行,那麼一般情況下可能需要進行一次全表掃描。但如果以這個年齡段建個索引,那麼索引中會按年齡值建一個排列,這樣在索引中就能迅速定位,不需要進行全表掃描。

爲什麼性別不適合建索引呢?因爲你訪問索引需要付出額外的IO開銷,你從索引中拿到的只是地址,要想真正訪問到數據還是要對錶進行一次IO。假如你要從表的100萬行數據中取幾個數據,那麼利用索引迅速定位,訪問索引的這IO開銷就非常值了。但如果你是從100萬行數據中取50萬行數據,就比如性別字段,那你相對需要訪問50萬次索引,再訪問50萬次表(非聚集索引會先找主鍵,也就是回表),加起來的開銷並不會比直接對錶進行一次完整掃描小。同時,雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行 INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅要保存數據還要更新索引。建立索引會佔用磁盤空間。一般情 況這個問題不太嚴重,但如果你在一個大表上創建了多種組合索引,索引文件的會膨脹很快。

當然凡事不是絕對,如果把性別字段設爲表的聚集索引,那麼就肯定能加快大約一半該字段的查詢速度了。聚集索引指的是表本身中數據按哪個字段的值來進行排序。因此,聚集索引只能有一個,而且使用聚集索引不會付出額外IO開銷(一級索引,非聚集索引是二級索引,額外一次io)。當然你得能捨得把聚集索引這麼寶貴資源用到性別字段上。

由於重複率高,那麼一個重複值就會根據索引去表中進行多次查詢,每次查詢就是一次io,而遍歷表就需要一次io,所以重複率高帶來的額外io開銷是很大的。

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