目錄
一、概述
二、資料庫為什麼要設計索引?
三、雜湊(hash)比樹(tree)更快,索引結構為什麼要設計成樹型?
四、資料庫索引為什麼使用b+樹?
五、為什麼m叉的b+樹比二叉搜尋樹的高度大大降低?
六、總結
資料庫索引是為了提高查詢速度而對表字段附加的一種標識。簡單來說,索引其實是一種資料結構。資料庫的索引類似於書籍的索引。在書籍中,索引允許使用者不必翻閱完整個書就能迅速地找到所需要的資訊。在資料庫中,索引也允許資料庫程式迅速地找到表中的資料,而不必掃瞄整個資料庫。
首先我們需要明白為什麼索引會提高查詢速度,資料庫在執行一條sql語句的時候,預設掃瞄方式是根據搜尋條件進行全表掃瞄,遇到匹配條件的就加入搜尋結果集合。如果我們對某一欄位增加索引,查詢時就會先去索引列表中一次定位到特定值的行數,大大減少遍歷匹配的行數,所以資料庫索引能明顯提高查詢的速度。
下面列舉幾種適合建立索引的情況:
經常在where條件中作為查詢條件的字段可以建立索引;
外來鍵關聯列可以建立索引;
order by排序後面的字段可以建立索引;
group by分組後的字段可以建立索引;
.......
當然,並不是所有情況下都適合建立索引,如下幾種情況就不太適合建立索引:
經常增、刪、改的字段不適合建立索引,每次執行,索引需重新建立;
資料過濾性很差的字段不適合建立索引,如性別字段;
當表資料量過少的時候不太適合建立索引,因為索引占用儲存空間;
..........
舉個最簡單的例子,小時候我們遇到不會讀的字,是不是拿出《新華字典》,大家都知道一本《新華字典》裡面有成千上萬個字,如何快速的找到我們不會讀的那個字呢?
《新華字段》最前面幾頁列出了我們漢字的筆畫索引,如下圖:
通過筆畫索引表查詢,我們是不是可以大大縮小我們查詢的範圍了,資料庫索引的作用大體相似。假設資料庫中存在1000萬條資料,如何能夠在最短的時間內搜尋到滿足條件的記錄呢,顯然可以引入索引來解決。
加速查詢速度的資料結構,常見的有兩類:
(1)、雜湊,例如hashmap,查詢/插入/修改/刪除的平均時間複雜度都是o(1);
(2)、樹,例如平衡二叉搜尋樹,查詢/插入/修改/刪除的平均時間複雜度都是o(lg(n));
可以看到,不管是讀請求,還是寫請求,雜湊型別的索引,都要比樹型的索引更快一些。
那為什麼索引結構要設計成樹型呢?
索引設計成樹形,和sql的需求相關。對於單行查詢的sql,如:
select * from user t where t.user_id = "1356894556";
因為上述每次查詢肯定都只會返回一條記錄,所以索引結構使用hash的話,確實會比用樹結構快。
但是,資料庫中的查詢並不僅僅只有單行查詢,還有分組group by、排序oder by 等等。
遇上如上除了單行查詢的情況,如果使用hash索引的話,時間複雜度會退化為o(n),而如果使用樹型索引的話,由於樹的「有序」特性,依然能夠保持o(log(n)) 的高效率,時間複雜度不會退化。
另外,hash索引可能會存在hash衝突情況。資料結構中,樹主要有以下幾種:
二叉搜尋樹;
b樹;b+樹;
二叉搜尋樹,也是最簡單的樹結構。主要特徵:
若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
左、右子樹也分別為二叉排序樹;
那麼,二叉搜尋樹為什麼不適合用作資料庫索引?
(1)、當資料量大的時候,樹的高度會比較高,資料量大的時候,查詢會比較慢;
(2)、每個節點只儲存乙個記錄,可能導致一次查詢有很多次磁碟io;
b樹特徵:
樹中每個結點最多含有m個孩子(m>=2);
除根結點和葉子結點外,其它每個結點至少有[ceil(m / 2)]個孩子(其中ceil(x)是乙個取上限的函式);
葉子節點,非葉子節點,都儲存資料;
中序遍歷,可以獲得所有節點;
若根結點不是葉子結點,則至少有2個孩子(特殊情況:沒有孩子的根結點,即根結點為葉子結點,整棵樹只有乙個根節點);
b樹為什麼適合做索引?
(1)、b樹結構是m分叉的,高度能夠大大降低;
(2)、每個節點可以儲存j個記錄,如果將節點大小設定為頁大小,例如4k,能夠充分的利用預讀的特性,極大減少磁碟io;
b+樹葉是m叉搜尋樹,在b樹的基礎上,做了一些改進:
非葉子節點不再儲存資料,資料只儲存在同一層的葉子節點上;
葉子之間,增加了鍊錶,獲取所有節點,不再需要中序遍歷;
葉子節點儲存實際記錄行,記錄行相對比較緊密的儲存,適合大資料量磁碟儲存;非葉子節點儲存記錄的pk,用於查詢加速,適合記憶體儲存;
非葉子節點,不儲存實際記錄,而只儲存記錄的key的話,那麼在相同記憶體的情況下,b+樹能夠儲存更多索引;
大概計算一下:
(1)、區域性性原理,將乙個節點的大小設為一頁,一頁4k,假設乙個key有8位元組,乙個節點大約可以儲存500個key,即j = 500;(1kb = 1024位元組 ,4kb = 4096位元組, 4096 / 8 = 512個)
(2)、m叉b+樹,大概m / 2 <= j <= m,即可以差不多是1000叉樹;
(3)、那麼:
一層樹:1個節點,1 * 500個key,大小4k;
二層樹:1000個節點,1000 * 500 = 50w個key,大小1000 * 4k = 4m
三層樹:1000 * 1000個節點,1000 * 1000 * 500 = 5億個key,大小1000 * 1000 * 4k = 4g
可以看到,儲存大量的資料(5億),並不需要太高樹的深度(高度3),索引也不是太佔記憶體(4g)。
(1)、很適合磁碟儲存,能夠充分利用區域性性原理,磁碟預讀;
(2)、很低的樹高度,能夠儲存大量資料;
(3)、索引本身占用的記憶體很小;
(4)、能夠很好的支援單點查詢,範圍查詢,有序性查詢;
cache是什麼?作用是什麼?位置在哪?
參考 01 02 高速緩衝儲存器 cache 實際上是為了把由dram組成的大容量記憶體儲器都看做是高速儲存器而設定的小容量區域性儲存器,一般由高速sram構成。這種區域性儲存器是面向cpu的,引入它是為減小或消除cpu與記憶體之間的速度差異對系統效能帶來的影響。cache 通常儲存著乙份記憶體儲器...
IP位址是什麼,IP的作用是什麼?
網際網路是二十一世紀最重要的產物之一,在網際網路上各個節點分布著很多東西,有 伺服器 交換機 乃至我們的個人pc機等,再連通這些裝置的過程中,ip發揮著扮演者乙個舉足輕重的角色,今天我們就從日常生活的角度,帶領大家去認識這個伴隨著我們每乙個人的事物。1 寬頻基本上是家家戶戶都有,通過了向營運商付費,...
IFNULL的作用是什麼?
下面乙個簡單的sql和結果說明,如果ifnull a,b a接收的值為null,則返回b,否則返回a select ifnull null,0 select ifnull score,0 from student where id 4 按照ifnull函式的作用,應該返回0才對,可是結果並不是這樣。...