Mysql(12)—哈希索引的数据结构以及索引的优缺点

Posted 刘Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql(12)—哈希索引的数据结构以及索引的优缺点相关的知识,希望对你有一定的参考价值。

上一篇文章中,我们专门介绍了BTREE索引的数据结构以及底层实现,现在我们看看其他哈希索引结构的实现,以及索引的优缺点。

1 索引的优缺点

索引可以让服务器快速的定位到表的指定位置。但是这并不是索引的唯一作用,总结下来索引有以下4个优点:

  1. 索引大大减少了服务器需要扫描的数据量。
  2. B-Tree索引可以帮助服务器避免排序和临时表,,可以用于 ORDER BY 和 GROUP BY 操作,临时表主要是在排序和分组过程中创建,不需要排序和分组,也就不需要创建临时表。
  3. 由于索引中存储了实际的列值,所以某些查询可以只使用索引就能完成全部查询,甚至避免回表查询。
  4. B-Tree索引数据都是有序的,可以将随机I/O变为顺序I/O,顺序读取不需要进行磁盘寻道,并且只需要很短的磁盘旋转时间,速度会非常快。并且可以利用预读特性,相邻的节点也能够被预先载入。

索引的缺点:

  1. 索引本身也是表,因此会占用存储空间,创建和维护索引需要耗费空间和时间成本,这个成本随着数据量增大而增大;
  2. 构建索引会降低数据表的修改操作(删除,添加,修改)的效率,因为在修改数据表的同时还需要修改索引表。

大多数情况下,中到大型的表索引查询都是比全表扫描要快的。但是对于非常小的表(数据量很少),那么简单的全表扫描更高效。

但是对于特大型的表,建立和维护索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。

2 哈希索引

哈希索引(hash index)基于哈希表实现。哈希索引通过Hash算法(直接定址法、平方取中法、折叠法、除数取余法、随机数法)将数据库的索引列数据转换成定长的哈希码作为key,将这条数据的行的地址作为value一并存入Hash表的对应位置。

mysql中,只有Memeory引擎显式的支持哈希索引,这也是Memory引擎表的默认索引结构,Memeory同时也支持B-Tree索引。并且,Memory引擎支持非唯一哈希索引,如果多个列的哈希值相同(或者发生了Hash碰撞),索引会在对应Hash键下以链表形式存储多个记录地址。

哈希索引还有如下特点:

  1. 哈希索引不支持部分索引列的匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。例如,在数据列(A,B)上建立哈希索引,如果查询只有数据列A,则无法使用该索引。
  2. 哈希索引具有哈希表的特性,因此只有精确匹配所有列的查询对于哈希索引才有效,比如=、<>、IN(,因为数据的存储是无序的),且无法使用任何范围查询。
  3. 因为数据的存储是无序的,哈希索引还无法用于排序。
  4. 对于精确查询,则哈希索引效率很高,时间复杂度为O(1),除非有很多哈希冲突(不同的索引列有相同的哈希值),如果发生哈希冲突,则存储引擎必须遍历链表中的所有数据指针,逐行比较,直到找到所有符合条件的行。哈希冲突越多,代价就越大!

基于以上的限制,哈希索引只适用于某些特定的场合,但是一旦适合哈希索引,则它带来的性能提升是非常显著的。

InnoBD引擎有一个特殊的功能叫“自适应哈希索引”。当InnoDB注意到某些索引值被使用得非常频繁时,它会在内存中基于B-Tree索引之上再创建一个哈希索引,这样就让B-Tree索引也具有哈希索引的一些优点,比如快速的哈希查找。但这是一个完全自动的、内部的行为,用于无法控制,但用户可以选择完全关闭该动能。

在使用InnoBD引擎时,我们可以在B-Tree的基础上创建一个伪哈希索引。当然这不是真正的哈希索引,因为还是使用的B-Tree进行查找,但它使用哈希值而不是键本身进行索引查找。

例如,如果需要存储大量的URL并且需要根据URL进行查找,如果使用B-Tree来存储URL,则存储的内容就会很大,因为URL本身就很长。为此,我们可以单独指定一个哈希列并为该列创建索引,并选择一个哈希函数!每次存储、变更URL时,对该URL应用一个函数计算出一个哈希值,存入对应的哈希列中。

在查询时,如果采用体积很小的基于哈希值的索引来查找,则性能会提升很多,唯一的缺点就是需要委会一个哈希函数,为此我们可以使用触发器来实现。

如果出现了哈希冲突,则查询会返回多行数据,为此在查询时还必须带上真正的URL常量值。正确的查询语句为:select xx from url where url_hash = hash(‘https://www.baidu.com/’) AND url = ‘https://www.baidu.com/’;

3 全文索引

全文索引是一种特殊类型索引,用于查找文本中的关键词,而不是直接比较是否相等。全文索引的和其他索引的匹配方式完全不一样,全文索引更类似于搜索引擎做的事情,查找条件使用 MATCH AGAINST,而不是普通的 WHERE。

全文索引使用倒排索引实现,它记录着关键词到其所在文档的映射。

MyISAM存储引擎支持全文索引,InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始支持全文索引。

4 空间数据索引(R-Tree)

MyISAM存储引擎支持空间数据索引(R-Tree),可以用于地理数据存储。空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。

必须使用 GIS 相关的函数来维护数据。

下一篇文章中,我们将介绍一些高性能的索引策略以及索引失效的情况和索引优化策略,在面试中会经常问道。

参考资料:

  1. 《 MySQL 技术内幕: InnoDB 存储引擎》
  2. 《高性能 MySQL》

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

以上是关于Mysql(12)—哈希索引的数据结构以及索引的优缺点的主要内容,如果未能解决你的问题,请参考以下文章

Mysql(13)—高性能的索引策略以及常见索引失效的情况

运维丨mysql高级学习之索引的优劣势及规则使用

MySQL索引原理及优化

机器学习时代哈希算法如何高效索引数据?

机器学习时代的哈希算法,将如何更高效地索引数据

mysql-哈希索引