mysql索引(四)索引的數(shù)據(jù)結(jié)構(gòu)HASH

我們常用的索引數(shù)據(jù)結(jié)構(gòu)比較多的是B+TREE。

還有另一種索引數(shù)據(jù)結(jié)構(gòu)是hash,但是innoDB、mysiam數(shù)據(jù)引擎不支持hash數(shù)據(jù)結(jié)構(gòu)。

不同的存儲引擎支持的索引類型也不一樣:

InnoDB 支持事務(wù),支持行級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;

MyISAM 不支持事務(wù),支持表級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;

Memory 不支持事務(wù),支持表級別鎖定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;

NDB 支持事務(wù),支持行級別鎖定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;

Archive 不支持事務(wù),支持表級別鎖定,不支持 B-tree、Hash、Full-text 等索引;

這個玩意,mysiam和innodb是不支持的,所以,一般情況下用不上了解就好。

一:hash算法復(fù)雜度

哈希算法時間復(fù)雜度為O(1),且不只存在于索引中,每個數(shù)據(jù)庫應(yīng)用中都存在該數(shù)據(jù)結(jié)構(gòu)。

二:HASH索引特性

在MySQL的存儲引擎中,MyISAM不支持哈希索引,而InnoDB中的hash索引是存儲引擎根據(jù)B-Tree索引自建的,后面會對其做具體說明。

hash索引的特點

1、 hash索引是基于hash表實現(xiàn)的,只有查詢條件精確匹配hash索引中的所有列的時候,才能用到hash索引。

2、 對于hash索引中的所有列,存儲引擎都會為每一行計算一個hash碼,hash索引中存儲的就是hash碼。

3、 hash索引包括鍵值、hash碼和指針 。

因為hash索引本身只需要存儲對應(yīng)的hash值,所以索引的結(jié)構(gòu)十分緊湊,這也讓hash索引查找的速度非???。然而,hash索引也是存在其限制的:

三:hash索引的限制

1、 Hash索引必須進行二次查找

使用哈市索引兩次查找,第一次找到相應(yīng)的行,第二次讀取數(shù)據(jù),但是被頻繁訪問到的行一般會緩存在內(nèi)存中,這點對數(shù)據(jù)庫性能的影響不大。
  
2、hash索引不能用于外排序
hash索引存儲的是hash碼而不是鍵值,所以無法用于外排序
  
3、hash索引不支持部分索引查找也不支持范圍查找

只能用到等值查詢,不能范圍和模糊查詢
  
4、hash索引中的hash碼的計算可能存在hash沖突

當出現(xiàn)hash沖突的時候,存儲引擎必須遍歷整個鏈表中的所有行指針,逐行比較,直到找到所有的符合條件的行,若hash沖突很多的話,一些索引的維護代價機會很高,所以說hash索引不適用于選擇性很差的列上(重復(fù)值很多)。姓名、性別、身份證(合適)

上面說到InnoDB的“自適應(yīng)hash索引”。就是當InnoDB注意到某些索引值被使用的非常頻繁時,它會在內(nèi)存中基于B-Tree索引上在創(chuàng)建一個hash索引,這樣就讓B-tree索引也具有hash索引的一些優(yōu)點。這是一個完全自動的內(nèi)部的行為,用戶無法控制或配置,不過,如果有需要,完全可以關(guān)閉該功能。

四:創(chuàng)建自定義hash索引

若存儲引擎不支持hash索引,又想擁有hash索引所帶來的性能提升,則可以模擬InnoDB一樣創(chuàng)建哈希索引。

思路也比較簡單,就是在B-tree基礎(chǔ)上創(chuàng)建一個偽哈希索引。這和真正的hash索引不是一回事,因為還是采用B-Tree進行查找,但是它使用的是hash值而不是鍵本身進行查找。只需要在查詢的where子句中手動指定使用hash函數(shù)即可。下面舉個簡單的例子:

比如:當我們需要存儲大量的URL,并需要根據(jù)URL進行搜索查找。若用B-Tree來存儲URL,存儲的內(nèi)容就會很大。此時的查詢語句就是:

select id from url where url = "www.baidu.com";

若刪除原來的url列上的索引,而新增一個被索引的url_crc列,使用crc32做hash函數(shù),則可以使用如下方式查詢:

select id from url where url = "www.baidu.com" and url_crc=CRC32("www.baidu.com");

這樣做的話,性能就會有很大提升,因為mysql優(yōu)化器會使用這個選擇性高而體積很小的基于url_crc列的多音來完成查找。即使有多個記錄相同的索引值,查找仍然很快,只需要根據(jù)hash值做快速的整數(shù)比較就能找到索引條目,然后一一返回對應(yīng)的行。

五:Hash缺點

1、需要維護hash值,可以手動維護,也可以使用觸發(fā)器實現(xiàn)。
2、若數(shù)據(jù)表非常大的話,CRC32()會出現(xiàn)大量hash沖突,則可以自己實現(xiàn)一個64位的hash函數(shù),這個自定義的hash函數(shù)要返回整數(shù)而不是字符串,因為范圍整數(shù),對此效率更高。一個簡單的辦法就是使用MD5()函數(shù)返回值的一部分來作為自定義的hash函數(shù)。但是這可能比自己寫一個hash算法性能要差一些。

以上大概就是hash索引的基本內(nèi)容。

再說一次,這個玩意他不支持mysiam和innodb,所以,可能是用的不多。

有好的建議,請在下方輸入你的評論。

歡迎訪問個人博客
https://guanchao.site

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容