深入淺出索引(上)

2021-09-25 11:53:12 字數 3599 閱讀 1042

我們都知道資料庫的索引是用來提公升檢索速度的,但是索引究竟內部是怎麼工作的呢,就來說說這個話題8

索引就像書的目錄一樣,幫助我們更快的查詢到我們需要的資料。

索引的種類有很多種,接下來主要介紹三種常見,也比較簡單的資料結構,分別是雜湊表,有序陣列和搜尋樹。

然後從使用的角度分析一下,三者的區別:

雜湊表是一種kv儲存資料的形式,只要輸入待查詢的值,比如說是key,就可以找到value。

但如果多個k對應乙個v,那麼就會拉出乙個鍊錶。

那麼我們該如何在這種情況下,找到我們需要的那個v呢,可以看如下解釋。

假如有一張表,只有身份證號和姓名,需要根據身份證號找到姓名

這時候我們發現,id-card-n2和id-card-n4計算出的雜湊值都為n,並且n對應著一張鍊錶,那麼,假如我們要利用id-card-n2找出name2,該怎麼辦呢?

首先,將id-card-n2通過雜湊函式計算出n,然後按照順序遍歷找到user2。

有序雜湊,插入不方便,區間查詢方便,無序雜湊,插入方便(指的是順延插入),區間查詢不方便。

所以,雜湊表這種結構適用於等值查詢的場景。

如果以上的情況,我們用有序陣列實現的話,示意圖如下:

假設身份證賬號沒有重複,陣列按照底層去儲存,如果要查詢id-card-n2對應的名字,用二分法就可以查詢到,這個時間複雜度是logn、

並且這個索引結構支援範圍查詢。而且查詢效率也是相當高的。但是如果插入,就很麻煩,因為每乙個都需要往後瞬移乙個單位。

所以,有序陣列只能進行靜態儲存引擎,就是那種不會修改的資料。

二叉搜尋樹是非常經典的資料結構,也用上面的例子,效果如下:

二叉搜尋樹的特點是:每個節點的左兒子小於父節點,父節點又小於右兒子。

當然為了維持o(log(n))的查詢複雜度,你就需要保持這棵樹是平衡二叉樹。為了做這個保證,更 新的時間複雜度也是o(log(n))。

為了能夠讓乙個查詢更少的讀取總儲存,應該查詢的時候訪問更少的資料塊,所以就不能使用二叉樹,而是多叉樹,至於多少叉,取決於資料塊的大小,但是總體都滿足大小從左往右遞增。

以innodb的乙個整數字段索引來說,n差不多是1200,當樹高為4的時候,就可以儲存1200的3次方個值,但是考慮到樹根 是在記憶體的,所以訪問速度相當快,只需要訪問三次硬碟。

在mysql中,索引是在儲存引擎層實現的,所以沒有統一的索引標準,即不同儲存引擎的索引方式是不同的,以下以常用的innodb來說一下。

在innodb中,表都是根據主鍵順序以索引的形式發放的,這種儲存形式的表稱為索引組織表。

innodb使用了b+樹索引模型,所以資料都是儲存在b+樹的。

每乙個innodb索引都有乙個b+樹。

假設,我們有乙個主鍵列為id的表,表中有字段k,並且在k上有索引。

建表語句如下:

mysql>

create

table t3(

id int

unique

key,

k int

notnull

, name varchar(16

),index

(k))

engine

=innodb

;

query ok,

0rows affected (

0.03 sec)

然後插入語句

mysql>

insert

into t3 (id,k,name)

values

(100,1

,'r1');

query ok,

1row affected (

0.00 sec)

mysql>

insert

into t3 (id,k,name)

values

(200,2

,'r2'

);

query ok,

1row affected (

0.09 sec)

mysql>

insert

into t3 (id,k,name)

values

(300,3

,'r3');

query ok,

1row affected (

0.00 sec)

mysql>

insert

into t3 (id,k,name)

values

(500,5

,'r4');

query ok,

1row affected (

0.00 sec)

mysql>

insert

into t3 (id,k,name)

values

(600,6

,'r5'

);

query ok,

1row affected (

0.01 sec)

兩棵樹的示例圖如下:

可從圖看出,根據葉子節點的內容,索引型別分為主鍵索引和非主鍵索引。

主鍵索引的葉子結點儲存整行資料。

非主鍵索引的葉子結點內容是主鍵的值。

那麼,基於主鍵索引和普通索引的查詢有什麼區別?

也就是說,基於非主鍵索引的查詢需要多掃瞄一棵索引樹。

b+樹為了維護索引的有序性,在插入新值的時候需要做必要的維護。如果插入的新id=700,則只需要在r5後面插入即可,如果id=400,就需要讓r5往後退乙個流出位置。

更加糟糕的情況是,如果資料頁已經滿了,就得需要申請乙個新的資料頁,那麼這個過程就叫做頁**,效能會降低很多。

除了效能,還會影響資料頁的利用率,原本是放在乙個頁資料,現在分到兩個頁中,整體利用率降低50%。

既然有頁**也會有頁合併,當相鄰兩個頁由於刪除了資料,利用率很低之後,會將資料頁做合併。

在建表的時候,這樣來定義自增主鍵。

not null primary key auto_increment

插入的時候不用指定自增的主鍵。

從業務角度去考慮,如果你的表內有除了自增主鍵以外的唯一字段,那麼是用自增主鍵還是用唯一欄位呢。

由於每個非主鍵索引的葉子節點上都是主鍵的值,如果用唯一字段,那麼每個二級索引的葉子節點占用n(具體長度由唯一字段長度決定)位元組,如果用整形做主鍵,則只需要4位元組,如果是長整型就需要8位元組。

顯然,主鍵長度越小,普通索引占用空間就越少。

所以,從效能和儲存空間方面考量,自增主鍵往往是更合理的選擇。

04 深入淺出索引(上)

1.索引的作用 提高資料查詢效率,就像書的目錄一樣。2.常見索引模型 雜湊表 有序陣列 搜尋樹 3.雜湊表 鍵 值 key value 4.雜湊思路 把值放在陣列裡,用乙個雜湊函式把key換算成乙個確定的位置,然後把value放在陣列的這個位置 5.雜湊衝突的處理辦法 鍊錶 6.雜湊表適用場景 只有...

03 深入淺出索引上下

三種索引 全文索引,雜湊索引,b 樹索引 索引維護 頁 隨機插入,向右 索引的選擇 身份證id or 自增主鍵 效能 儲存。效能 身份證id,是隨機插入,頁 是中間 可能會造成一定的儲存浪費,次數頁比較多。但是自增主鍵,只有頁滿才會將新點 到下乙個頁,效率是最高的。儲存 乙個b 樹節點,儲存的身份證...

MySQL學習 3 深入淺出索引(上)

innodb的索引模型 參考資料 寫在後面 環境 mysql5.7.24,for linux glibc2.12 x86 64 簡單來說,索引的出現其實就是為了提高資料查詢 的效率,就像書的目錄一樣。對於資料庫的表而言,索引其實就是它的 目錄 用於提高讀寫效率的資料結構有很多,以下介紹三種常見 也比...