深入淺出資料庫索引原理

2022-05-01 22:06:09 字數 4104 閱讀 3655

建立索引很簡單,但是能深入理解索引原理又能恰到好處使用索引又是另外一回事。

為什麼要給表加上主鍵?

我們平時建表的時候都會為表加上主鍵, 在某些關聯式資料庫中, 如果建表時不指定主鍵,資料庫會拒絕建表的語句執行。 事實上, 乙個加了主鍵的表,並不能被稱之為「表」。乙個沒加主鍵的表,它的資料無序的放置在磁碟儲存器上,一行一行的排列的很整齊, 跟我認知中的「表」很接近。如果給表上了主鍵,那麼表在磁碟上的儲存結構就由整齊排列的結構轉變成了樹狀結構,也就是上面說的「平衡樹」結構,換句話說,就是整個表就變成了乙個索引。

沒錯, 再說一遍, 整個表變成了乙個索引,也就是所謂的「聚集索引」。 這就是為什麼乙個表只能有乙個主鍵, 乙個表只能有乙個「聚集索引」,因為主鍵的作用就是把「表」的資料格式轉換成「索引(平衡樹)」的格式放置。

講完聚集索引 , 接下來聊一下非聚集索引, 也就是我們平時經常提起和使用的常規索引。

非聚集索引和聚集索引一樣, 同樣是採用平衡樹作為索引的資料結構。索引樹結構中各節點的值來自於表中的索引字段, 假如給user表的name欄位加上索引 , 那麼索引就是由name欄位中的值構成,在資料改變時, dbms需要一直維護索引結構的正確性。如果給表中多個字段加上索引 , 那麼就會出現多個獨立的索引結構,每個索引(非聚集索引)互相之間不存在關聯。 如下圖

每次給字段建乙個新索引, 欄位中的資料就會被複製乙份出來, 用於生成索引。 因此, 給表新增索引,會增加表的體積, 占用磁碟儲存空間。

非聚集索引和聚集索引的區別在於, 通過聚集索引可以直接查到需要查詢的資料, 而通過非聚集索引可以查到記錄對應的主鍵值 ,再使用主鍵的值通過聚集索引查詢到需要的資料,如下圖

不管以任何方式查詢表, 最終都會利用主鍵通過聚集索引來定位到資料, 聚集索引(主鍵)是通往真實資料所在的唯一路徑。

然而, 有一種例外可以不使用聚集索引就能查詢出所需要的資料, 這種非主流的方法 稱之為「覆蓋索引」查詢, 也就是平時所說的組合索引、復合索引或者多欄位索引查詢。 文章上面的內容已經指出, 當為字段建立索引以後, 欄位中的內容會被同步到索引之中,如果為乙個索引指定兩個字段, 那麼這個兩個欄位的內容都會被同步至索引之中

先看下面這個sql語句

//

建立索引

create

index index_birthday on

user_info(birthday);

//查詢生日在2023年11月1日出生使用者的使用者名稱

select

user_name

from user_info where birthday =

'1991-11-1

'

這句sql語句的執行過程如下

首先,通過非聚集索引index_birthday查詢birthday等於1991-11-1的所有記錄的主鍵id值

然後,通過得到的主鍵id值執行聚集索引查詢,找到主鍵id值對就的真實資料(資料行)儲存的位置

最後, 從得到的真實資料中取得user_name欄位的值返回, 也就是取得最終的結果

我們把birthday欄位上的索引改成雙字段的覆蓋索引,

create

index index_birthday_and_user_name on user_info(birthday, user_name);

通過非聚集索引index_birthday_and_user_name查詢birthday等於1991-11-1的葉節點的內容,然而, 葉節點中除了有user_name表主鍵id的值以外, user_name欄位的值也在裡面, 因此不需要通過主鍵id值的查詢資料行的真實所在, 直接取得葉節點中user_name的值返回即可。 通過這種覆蓋索引直接查詢的方式, 可以省略不使用覆蓋索引查詢的後面兩個步驟, 大大的提高了查詢效能,如下圖

再詳細說下這個覆蓋索引,也叫組合索引

組合索引,即乙個索包含多個列。(當乙個表中查詢大的情況下,where條件中有多個,那麼可以使用組合查詢,不會掃瞄表,直接從索引中獲取,查詢效率高)

它遵循最左字首匹配原則,也是就是說乙個查詢可以只使用復合索引最左側的一部份。例如索引是key index (a,b,c). 可以支援a | a,b| a,b,c 3種組合進行查詢,但不支援 b,c進行查詢 .當最左側欄位是常量引用時,索引就十分有效。

因為組合索引建立的時候先對第一維排序,再對第二維,再對第三維...(非常不嚴謹的說法,但便於初學者理解)

對於如下表結構:

create

table

test(

a int,

b int,

c int,

keya(a,b,c)

);

那麼我們看一下下列語句:

優: select

*from test where a=

10and b>

50差:

select

*from test where b =

50優:

select

*from test orderbya

差: select

*from test orderbyb

差: select

*from test orderbyc

優: select

*from test where a=

10orderbya

優: select

*from test where a=

10orderbyb

差: select

*from test where a=

10orderbyc

優: select

*from test where a>

10orderbya

差: select

*from test where a>

10order

by b //

其實會索引失效

差: select

*from test where a>

10orderbyc

優: select

*from test where a=

10and b=

10orderbya

優: select

*from test where a=

10and b=

10orderbyb

優: select

*from test where a=

10and b=

10orderbyc

優: select

*from test where a=

10and b=

10orderbya

優: select

*from test where a=

10and b>

10orderbyb

差: select

*from test where a=

10and b>

10order

by c

重點:如果where條件第乙個引數取範圍值,會導致索引失效(>或者《等相關範圍查詢),後面的索引也會失效。

比如:select * from test where a>10 order by b組合索引失效。

注:在建立多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。

1. 知乎專欄-深入淺出資料庫索引原理

2. csdn_xlxxcc-mysl單列索引和組合索引

3. csdn_工作qq感冒的石頭-mysql多個單列索引和聯合索引的區別詳解

資料庫索引的深入淺出

了不了解索引的原理,其實根據資料的大小有很大的關係,其實很多事情你會發現,資料量1萬以下不是個事情,但是如果資料量達到了1000萬之類的量級,那麼優化,查詢可能就是會成為瓶頸。所以說,很多系統都是資料量小都不是問題,資料量一大,基本上就全是問題了。說白了,索引問題就是乙個查詢問題。資料庫索引,是資料...

深入淺出理解索引

一 深入淺出理解索引結構 實際上,您可以把索引理解為一種特殊的目錄。sql server提供了兩種索引 聚集索引 clustered index,也稱聚類索引 簇集索引 和非聚集索引 nonclustered index,也稱非聚類索引 非簇集索引 下面,我們舉例來說明一下聚集索引和非聚集索引的區別...

深入淺出理解索引

一 深入淺出理解索引結構 實際上,您可以把索引理解為一種特殊的目錄。sql server提供了兩種索引 聚集索引 clustered index,也稱聚類索引 簇集索引 和非聚集索引 nonclustered index,也稱非聚類索引 非簇集索引 下面,我們舉例來說明一下聚集索引和非聚集索引的區別...