什麼是聚集索引 非聚集索引 覆蓋索引

2022-01-09 21:30:00 字數 3963 閱讀 2939

本文為筆者近來學習的筆記,在解釋覆蓋索引之前勢必簡單回顧一下索引基本知識?

索引是資料庫管理系統中乙個排序的資料結構,以協助快速查詢、更新資料庫表中資料。通常模擬為圖書目錄。

聚集索引中鍵值的邏輯順序決定了表中相應行的物理順序,例如**本,索引為(姓,名),資料值為**號,在乙個表中通常只有乙個聚集索引, 聚集索引對於那些經常要搜尋範圍值的列特別有效。使用聚集索引找到包含第乙個值的行後,便可以確保包含後續索引值的行在物理相鄰。

​ 例如,如果應用程式執行 的乙個查詢經常檢索某一日期範圍內的記錄,則使用聚集索引可以迅速找到包含開始日期的行,然後檢索表中所有相鄰的行,直到到達結束日期。這樣有助於提高此類查詢的效能。同樣,如果對從表中檢索的資料進行排序時經常要用到某一列,則可以將該錶在該列上聚集(物理排序),避免每次查詢該列時都進行排序,從而節 省成本。

當索引值唯一時,使用聚集索引查詢特定的行也很有效率。

一種索引,該索引中索引的邏輯順序與磁碟上行的物理儲存順序不同。我們可以這麼理解聚簇索引:索引的葉節點就是資料節點。而非聚簇索引的葉節點仍然是索引節點(例如儲存資料存放的位址,而非資料),有乙個指標指向對應的資料塊。

​ 我們的漢語字典的正文本身就是乙個聚集索引。比如,我們要查「安」字,就會很自然地翻開字典的前幾頁,因為「安」的拼音是「an」,而按照拼音排序漢字的字典是以英文本母「a」開頭並以「z」結尾的,那麼「安」字就自然地排在字典的前部。如果您翻完了所有以「a」開頭的部分仍然找不到這個字,那麼就說明您的字典中沒有這個字;同樣的,如果查「張」字,那您也會將您的字典翻到最後部分,因為「張」的拼音是「zhang」。也就是說,字典的正文部分本身就是乙個目錄,您不需要再去查其他目錄來找到您需要找的內容。我們把這種正文內容本身就是一種按照一定規則排列的目錄稱為「聚集索引」。

​ 如果您認識某個字,您可以快速地從自動中查到這個字。但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛才的方法找到您要查的字,而需要去根據「偏旁部首」查到您要找的字,然後根據這個字後的頁碼直接翻到某頁來找到您要找的字。但您結合「部首目錄」和「檢字表」而查到的字的排序並不是真正的正文的排序方法,比如您查「張」字,我們可以看到在查部首之後的檢字表中「張」的頁碼是672頁,檢字表中「張」的上面是「馳」字,但頁碼卻是63頁,「張」的下面是「弩」字,頁面是390頁。很顯然,這些字並不是真正的分別位於「張」字的上下方,現在您看到的連續的「馳、張、弩」三字實際上就是他們在非聚集索引中的排序,是字典正文中的字在非聚集索引中的對映。我們可以通過這種方式來找到您所需要的字,但它需要兩個過程,先找到目錄中的結果,然後再翻到您所需要的頁碼。我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱為「非聚集索引」。

主鍵索引(primary),以主鍵列作為索引,最常用的索引。

普通索引(index):以普通列作為索引,唯一任務是加快對資料的訪問速度,因此,應該只為那些最經常出現在查詢 條件(where column=)或者排序條件(orderby column)中的資料列建立索引。

唯一索引(unique):以唯一值作為索引,目的往往不是為了提高訪問速度,而只是為了避免資料出現重複。

組合索引(composite):多列組合起來作為索引,例如前文中提到的**簿,就是以姓+名的形式作為索引

​ innodb引用的是b+樹索引模型,前文中對索引的種類劃分為兩大類:主鍵(聚集)索引和非聚集索引,那麼問題就在於比較兩種索引的區別了,我們這裡建立一張學生表,其中包含欄位id設定主鍵索引、name設定普通索引、age(無處理),並向資料庫中插入4條資料:("小趙", 10)("小王", 11)("小李", 12)("小陳", 13)。

create table `student` (

`id` int(11) not null auto_increment comment '自增主鍵',

`name` varchar(32) collate utf8_bin not null comment '名稱',

`age` int(3) unsigned not null default '1' comment '年齡',

primary key (`id`),

key `i_name` (`name`)

) engine=innodb;

insert into student (name, age) values("小趙", 10),("小王", 11),("小李", 12),("小陳", 13);

此時表中的資料:

mysql> select * from student;

+----+------+-----+

| id | name | age |

+----+------+-----+

| 1 | 小趙 | 10 |

| 2 | 小王 | 11 |

| 3 | 小李 | 12 |

| 4 | 小陳 | 13 |

+----+------+-----+

4 rows in set (0.00 sec)

每乙個索引在 innodb 裡面對應一棵b+樹,那麼此時就存著兩棵b+樹:

可以發現區別在與葉子節點中,主鍵索引儲存了整行資料,而非主鍵索引中儲存的值為主鍵id

當我們執行以下語句:

select age from student where name = '小李';
執行順序:

在name索引樹上找到名稱為小李的節點 id為03

從id索引樹上找到id為03的節點 獲取所有資料

從資料中獲取欄位命為age的值12,返回.

這樣從非主鍵索引樹搜尋再回到主鍵索引樹搜尋的過程稱為:回表

回表一定程度上消耗效能,那麼如何降低這種效能損耗呢?於是提出了一種方法:覆蓋索引.

覆蓋索引(covering index ,或稱為索引覆蓋)即從非主鍵索引中就能查到的記錄,而不需要查詢主鍵索引中的記錄,避免回表的產生減少了樹的搜尋次數,顯著提公升效能。

如果乙個業務中,很多類似於根據姓名查詢年齡的業務,那麼可以將這些熱點業務重新根據(name , age)建立聯合索引,先刪除之前以name構建的索引:

alter table student drop index i_name;

alter table student add index i_name_age(name, age);

聯合索引:

再次執行如下sql:

select age from student where name = '小李';
執行流程:

在name,age聯合索引樹上找到名稱為小李的節點。

此時節點索引裡包含資訊age直接返回 12,從而避免回表。

當發起乙個索引覆蓋查詢時,在explain的extra列可以看到using index的資訊:

聚集索引,非聚集索引,覆蓋索引 原理

資料庫 和 資料庫索引 這兩個東西是在伺服器端開發領域應用最為廣泛的兩個概念,熟練使用資料庫和資料庫索引是開發人員在行業內生存的必備技能 使用索引很簡單,只要能寫建立表的語句,就肯定能寫建立索引的語句,要知道這個世界上是不存在不會建立表的伺服器端程式設計師的。然而,會使用索引是一回事,而深入理解索引...

聚集索引 非聚集索引

通常情況下,建立索引是加快查詢速度的有效手段。但索引不是萬能的,靠索引並不能實現對所有資料的快速訪問。事實上,如果索引策略和資料檢索需求嚴重不符的話,建立索引反而會降低查詢效能。因此在實際使用當中,應該充分考慮到索引的開銷,包括磁碟空間的開銷及處理開銷 如資源競爭和加鎖 例如,如果資料頻繁的更新或刪...

聚集索引和非聚集索引

聚集索引和非聚集索引 一 聚集索引和非聚集索引 聚集索引和非聚集索引的根本區別是表記錄的排列順序和與索引的排列順序是否一致,聚集索引表記錄的排列順序與索引的排列順序一致,優點是查詢速度快,因為一旦具有第乙個索引值的紀錄被找到,具有連續索引值的記錄也一定物理的緊跟其後。聚集索引的缺點是對錶進行修改速度...