濮阳杆衣贸易有限公司

主頁 > 知識庫 > MySQL btree索引與hash索引區(qū)別

MySQL btree索引與hash索引區(qū)別

熱門標(biāo)簽:湖南人工外呼系統(tǒng)多少錢 石家莊電商外呼系統(tǒng) 信陽穩(wěn)定外呼系統(tǒng)運(yùn)營商 芒果電話機(jī)器人自動化 申請外呼電話線路 日照旅游地圖標(biāo)注 廣東人工電話機(jī)器人 南通自動外呼系統(tǒng)軟件 百度地圖圖標(biāo)標(biāo)注中心

在MySQL中,大多數(shù)索引(如 PRIMARY KEY,UNIQUE,INDEX和FULLTEXT)都是在BTREE中存儲,但使用memory引擎可以選擇BTREE索引或者HASH索引,兩種不同類型的索引各自有其不同的使用范圍。

  • B樹索引具有范圍查找和前綴查找的能力,對于有N節(jié)點的B樹,檢索一條記錄的復(fù)雜度為O(LogN)。相當(dāng)于二分查找。
  • 哈希索引只能做等于查找,但是無論多大的Hash表,查找復(fù)雜度都是O(1)。

顯然,如果值的差異性大,并且以等值查找(=、 、>、in)為主,Hash索引是更高效的選擇,它有O(1)的查找復(fù)雜度。
如果值的差異性相對較差,并且以范圍查找為主,B樹是更好的選擇,它支持范圍查找。

一、HASH索引

利用哈希函數(shù),計算存儲地址,檢索時不需要像Btree那樣,從根節(jié)點開始遍歷,逐級查找。

Hash 索引結(jié)構(gòu)的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree 索引需要從根節(jié)點到枝節(jié)點,最后才能訪問到頁節(jié)點這樣多次的IO訪問,所以 Hash 索引的查詢效率要遠(yuǎn)高于 B-Tree 索引。

可能很多人又有疑問了,既然 Hash 索引的效率要比 B-Tree 高很多,為什么大家不都用 Hash 索引而還要使用 B-Tree 索引呢?任何事物都是有兩面性的,Hash 索引也一樣,雖然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也帶來了很多限制和弊端,主要有以下這些。

(1)Hash 索引僅僅能滿足”=”,”IN”和”=>”查詢,不能使用范圍查詢(查詢范圍時 慢)。

由于 Hash 索引比較的是進(jìn)行 Hash 運(yùn)算之后的 Hash 值,所以它只能用于等值的過濾,不能用于基于范圍的過濾,因為經(jīng)過相應(yīng)的 Hash 算法處理之后的 Hash 值的大小關(guān)系,并不能保證和Hash運(yùn)算前完全一樣。

(2)Hash 索引無法被用來避免數(shù)據(jù)的排序操作。

由于 Hash 索引中存放的是經(jīng)過 Hash 計算之后的 Hash 值,而且Hash值的大小關(guān)系并不一定和 Hash 運(yùn)算前的鍵值完全一樣,所以數(shù)據(jù)庫無法利用索引的數(shù)據(jù)來避免任何排序運(yùn)算;

(3)Hash 索引不能利用部分索引鍵查詢。

對于組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合并后再一起計算 Hash 值,而不是單獨(dú)計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進(jìn)行查詢的時候,Hash 索引也無法被利用。

(4)Hash 索引在任何時候都不能避免表掃描。

前面已經(jīng)知道,Hash 索引是將索引鍵通過 Hash 運(yùn)算之后,將 Hash運(yùn)算結(jié)果的 Hash 值和所對應(yīng)的行指針信息存放于一個 Hash 表中,由于不同索引鍵存在相同 Hash 值,所以即使取滿足某個 Hash 鍵值的數(shù)據(jù)的記錄條數(shù),也無法從 Hash 索引中直接完成查詢,還是要通過訪問表中的實際數(shù)據(jù)進(jìn)行相應(yīng)的比較,并得到相應(yīng)的結(jié)果。

(5)Hash 索引遇到大量Hash值相等的情況后性能并不一定就會比B-Tree索引高。

對于選擇性比較低的索引鍵,如果創(chuàng)建 Hash 索引,那么將會存在大量記錄指針信息存于同一個 Hash 值相關(guān)聯(lián)。這樣要定位某一條記錄時就會非常麻煩,會浪費(fèi)多次表數(shù)據(jù)的訪問,而造成整體性能低下。

二、B+樹

  • b+樹的查找過程

如圖所示,如果要查找數(shù)據(jù)項29,那么首先會把磁盤塊1由磁盤加載到內(nèi)存,此時發(fā)生一次IO,在內(nèi)存中用二分查找確定29在17和35之間,鎖定磁盤塊1的P2指針,內(nèi)存時間因為非常短(相比磁盤的IO)可以忽略不計,通過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內(nèi)存,發(fā)生第二次IO,29在26和30之間,鎖定磁盤塊3的P2指針,通過指針加載磁盤塊8到內(nèi)存,發(fā)生第三次IO,同時內(nèi)存中做二分查找找到29,結(jié)束查詢,總計三次IO。真實的情況是,3層的b+樹可以表示上百萬的數(shù)據(jù),如果上百萬的數(shù)據(jù)查找只需要三次IO,性能提高將是巨大的,如果沒有索引,每個數(shù)據(jù)項都要發(fā)生一次IO,那么總共需要百萬次的IO,顯然成本非常非常高。

  • b+樹性質(zhì)

1.索引字段要盡量的?。?/strong>

通過上面的分析,我們知道IO次數(shù)取決于b+數(shù)的高度h,假設(shè)當(dāng)前數(shù)據(jù)表的數(shù)據(jù)為N,每個磁盤塊的數(shù)據(jù)項的數(shù)量是m,則有h=㏒(m+1)N,當(dāng)數(shù)據(jù)量N一定的情況下,m越大,h越??;而m = 磁盤塊的大小 / 數(shù)據(jù)項的大小,磁盤塊的大小也就是一個數(shù)據(jù)頁的大小,是固定的,如果數(shù)據(jù)項占的空間越小,數(shù)據(jù)項的數(shù)量越多,樹的高度越低。這就是為什么每個數(shù)據(jù)項,即索引字段要盡量的小,比如int占4字節(jié),要比bigint8字節(jié)少一半。這也是為什么b+樹要求把真實的數(shù)據(jù)放到葉子節(jié)點而不是內(nèi)層節(jié)點,一旦放到內(nèi)層節(jié)點,磁盤塊的數(shù)據(jù)項會大幅度下降,導(dǎo)致樹增高。當(dāng)數(shù)據(jù)項等于1時將會退化成線性表。

2.索引的最左匹配特性(即從左往右匹配):

當(dāng)b+樹的數(shù)據(jù)項是復(fù)合的數(shù)據(jù)結(jié)構(gòu),比如(name,age,sex)的時候,b+數(shù)是按照從左到右的順序來建立搜索樹的,比如當(dāng)(張三,20,F)這樣的數(shù)據(jù)來檢索的時候,b+樹會優(yōu)先比較name來確定下一步的所搜方向,如果name相同再依次比較age和sex,最后得到檢索的數(shù)據(jù);但當(dāng)(20,F)這樣的沒有name的數(shù)據(jù)來的時候,b+樹就不知道下一步該查哪個節(jié)點,因為建立搜索樹的時候name就是第一個比較因子,必須要先根據(jù)name來搜索才能知道下一步去哪里查詢。比如當(dāng)(張三,F)這樣的數(shù)據(jù)來檢索時,b+樹可以用name來指定搜索方向,但下一個字段age的缺失,所以只能把名字等于張三的數(shù)據(jù)都找到,然后再匹配性別是F的數(shù)據(jù)了, 這個是非常重要的性質(zhì),即索引的最左匹配特性。

以上就是MySQL btree索引與hash索引區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于MySQL btree索引與hash索引的資料請關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • MySQL Hash索引和B-Tree索引的區(qū)別
  • 為什么MySQL數(shù)據(jù)庫索引選擇使用B+樹?
  • MySQL優(yōu)化中B樹索引知識點總結(jié)
  • 淺談MySQL的B樹索引與索引優(yōu)化小結(jié)
  • 獲取 MySQL innodb B+tree 的高度的方法
  • Mysql中的Btree與Hash索引比較
  • 淺析MysQL B-Tree 索引

標(biāo)簽:呼和浩特 阿里 沈陽 公主嶺 牡丹江 天津 惠州 合肥

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《MySQL btree索引與hash索引區(qū)別》,本文關(guān)鍵詞  MySQL,btree,索引,與,hash,區(qū)別,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《MySQL btree索引與hash索引區(qū)別》相關(guān)的同類信息!
  • 本頁收集關(guān)于MySQL btree索引與hash索引區(qū)別的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    昭平县| 历史| 大城县| 卢龙县| 凤阳县| 大化| 临江市| 卫辉市| 曲阜市| 洪泽县| 瓮安县| 巢湖市| 个旧市| 如东县| 五大连池市| 尚义县| 池州市| 衡山县| 通许县| 伊吾县| 丰宁| 洪泽县| 铜山县| 濮阳县| 建平县| 林甸县| 泽州县| 福海县| 策勒县| 寻甸| 陆良县| 万盛区| 盐城市| 抚宁县| 荔波县| 南漳县| 乳山市| 吐鲁番市| 柘荣县| 龙州县| 合水县|