深入理解MySQL哈希索引

325 阅读3分钟

本文正在参加「技术专题19期 漫谈数据库技术」活动

聊到优化SQL查询,首先想到的就是索引,相同结构和数据量的前提下,一个没有索引的表和有索引的表查询的效果是有很大差距的,但是在最初学习的时候,接触到的索引方面的知识点偏向命令,那么今天来聊聊MySQL的哈希索引概念。

索引含义

如果想通俗的理解MySQL的索引,最直观的案例是字典的目录,MySQL的索引完成了和字典目录类似的功能,当我们想使用字典查询一个汉字的时候,步骤大概是这样的:

1)获取汉字的拼音首字母,如果不知道读音的情况下获取汉字的偏旁笔画数

2)安装拼音首字母或者笔画数找到对应的字所在的页数

3)然后打开具体页,来认识这个字

同样,采用索引查询数据库的时候,首先不直接查询数据,而是通过索引结构查询到数据所在的位置然后直接访问位置,比如:

select username,password form auth_user where id = 1000;

如果这里已经在id这一列设置了索引,那么就不会直接到auth_user表当中查询id=1000的数据,而是先从索引的数据结构当中查找到id=1000的数据的行,然后返回数据行,这一点是不是和查字典的过程有相似呢,当然这样做的目的就是减少或者避免全文检索的问题,全文检索是效率很低的一种做法。

哈希索引

其实从名字上可以看出来这个索引是采用哈希表实现的,只有精确的匹配索引类的查询才有效,存储引擎会对所有的索引列计算一个哈希码,然后哈希索将所有的哈希码存放到索引中,同时在哈希表当中存放数据行的指针,比如:

-- 数据表
select * from auth_user;
+------------+------------+
| username   | password   | 
+------------+------------+
| admin      | 123        | 
| root       | 123456     | 
+------------+------------+-- 对username列创建哈希索引,假使使用h()来作为哈希函数,执行哈希函数,原理如下:
h(admin) = 3124
h(root)  = 3716-- 那么哈希索引的数据结构如下
+------------+------------+
| 槽         | 值          | 
+------------+------------+
| 3124       |1行指针    | 
| 3716       |2行指针    | 
+------------+------------+
-- 这个时候执行sql语句
select password from auth_user where username = "admin";
​
-- mysql先计算admin的哈希值。
-- 然后找到指针。
-- 然后根据指针获取第1行数据。
-- 最后判断一下第1行返回的username是不是admin来防止错判。

通过上面的例子发现,因为只存储哈希值,所以索引结构紧凑,查询速度快,当然,哈希索引也有限制:

1、索引当中只有哈希值和指针,所以没有办法避免读行(比如,如果在索引当中存放了password,那么只获取索引,不读行内数据就知道密码了)

2、哈希索引的数据不是按照索引值顺序存储的,所以无法用于排序。

3、哈希索引的哈希值是通过索引列完整的字段创建的,所以不支持部分查找。

4、哈希索引最害怕的就是索引值冲突(两行索引有了同样的hash值),解决这样的冲突成本很高。

使用场景

那什么时候适合使用哈希索引呢,比如:

通过网站地址来获取网站信息的常见,网站的地址可能很长,这个时候如果使用其他索引,比如b-tree,那么将url放到索引当中就会很大,那么就可以使用hash索引。

那么,关于哈希索引的理解就先聊这么多,还请小伙伴们多多指教。

本文正在参加「技术专题19期 漫谈数据库技术」活动