[原]MySQL哈希之哈希索引

mysql-log


0x00.About

索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。

从MySQL逻辑架构来看,MySQL有三层架构,第一层连接,第二层查询解析、分析、优化、视图、缓存,第三层,存储引擎。

MySQL逻辑架构

索引通过分开查询片,节省了扫描查找时间,大大提升查询效率。

大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构。

索引主要在存储引擎层上,不同的引擎也就有不同的B-Tree算法。



0x01.Hash Index

哈希索引只有Memory, NDB两种引擎支持,Memory引擎默认支持哈希索引,如果多个hash值相同,出现哈希碰撞,那么索引以链表方式存储。

但是,Memory引擎表只对能够适合机器的内存切实有限的数据集。

要使InnoDB或MyISAM支持哈希索引,可以通过伪哈希索引来实现,叫自适应哈希索引。

主要通过增加一个字段,存储hash值,将hash值建立索引,在插入和更新的时候,建立触发器,自动添加计算后的hash到表里。

直接索引

假如有一个非常非常大的表,如下:

CREATE TABLE IF NOT EXISTS `User` (
  `id` int(10) NOT NULL COMMENT '自增id',
  `name` varchar(128) NOT NULL DEFAULT '' COMMENT '用户名',
  `email` varchar(128) NOT NULL DEFAULT '' COMMENT '用户邮箱',
  `pass` varchar(64) NOT NULL DEFAULT '' COMMENT '用户密码',
  `last` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后登录时间',
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

这个时候,比如说,用户登陆,我需要通过email检索出用户,通过explain得到如下:

mysql> explain SELECT id FROM User WHERE email = ‘ooxx@gmail.com’ LIMIT 1;

+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | User  | ALL  | NULL          | NULL | NULL    | NULL | 384742 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+

发现 rows = 384742 也就是要在384742里面进行比对email这个字段的字符串。

这条记录运行的时间是:Query took 0.1744 seconds,数据库的大小是40万。

从上面可以说明,如果直接在email上面建立索引,除了索引区间匹配,还要进行字符串匹配比对,email短还好,如果长的话这个查询代价就比较大。

如果这个时候,在email上建立哈希索引,查询以int查询,性能就比字符串比对查询快多了。

Hash 算法

建立哈希索引,先选定哈希算法,这里选用CRC32。

《高性能MySQL》说到的方法CRC32算法,建立SHA或MD5算法是划算的,本身位数都有可能比email段长了。

INSERT UPDATE SELECT 操作

在表中添加hash值的字段:

mysql> ALTER TABLE User ADD COLUMN email_hash int unsigned NOT NULL DEFAULT 0;

接下来就是在UPDATE和INSERT的时候,自动更新 email_hash 字段,通过MySQL触发器实现:

DELIMITER |
CREATE TRIGGER user_hash_insert BEFORE INSERT ON `User` FOR EACH ROW BEGIN
SET NEW.email_hash=crc32(NEW.email);
END;
|
CREATE TRIGGER user_hash_update BEFORE UPDATE ON `User` FOR EACH ROW BEGIN
SET NEW.email_hash=crc32(NEW.email);
END;
|
DELIMITER ;

这样的话,我们的SELECT请求就会变成这样:

mysql> SELECT email, email_hash FROM User WHERE email_hash = CRC32(“F2dgTSWRBXSZ1d3O@gmail.com”) AND email = “F2dgTSWRBXSZ1d3O@gmail.com”;

+----------------------------+------------+
| email                      | email_hash |
+----------------------------+------------+
| F2dgTSWRBXSZ1d3O@gmail.com | 2765311122 |
+----------------------------+------------+

在没建立hash索引时候,请求时间是 0.2374 seconds,建立完索引后,请求时间直接变成 0.0003 seconds。

AND email = "F2dgTSWRBXSZ1d3O@gmail.com" 是为了防止哈希碰撞导致数据不准确。



0x02.Hash Index 缺点

哈希索引也有几个缺点:

  • 索引存放的是hash值,所以仅支持 < = > 以及 IN 操作
  • hash索引无法通过操作索引来排序,因为存放的时候经过hash计算,但是计算的hash值和存放的不一定相等,所以无法排序
  • 不能避免全表扫描,只是由于在memory表里支持非唯一值hash索引,就是不同的索引键,可能存在相同的hash值
  • 如果哈希碰撞很多的话,性能也会变得很差
  • 哈希索引无法被用来避免数据的排序操作



参考:

[1] Baron Scbwartz等 著,王小东等 译;高性能MySQL(High Performance MySQL);电子工业出版社,2010

[2] 《MySQL的B-Tree索引和Hash索引的区别》

[3] 《mysql 索引优化 btree hash rtree》


本文出自 夏日小草,转载请注明出处:http://homeway.me/2015/09/13/mysql-hash-index

-by小草

2015-09-13 15:49:10

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL哈希索引是一种用于加快数据检索速度的索引结构。哈希索引使用哈希函数将索引键映射到一个固定大小的哈希值,然后将哈希值与存储在内存中的哈希表进行匹配,以快速定位到所需的数据行。哈希索引的搜索时间复杂度为O(1),因为它直接通过哈希值进行查找,而不需要像B树索引那样进行逐层的比较。这使得哈希索引在某些特定场景下具有较高的检索效率。 然而,需要注意的是,MySQL哈希索引并非适用于所有情况。哈希索引的主要限制是它只支持等值查询,而不支持范围查询或排序操作。此外,哈希索引对于频繁的插入和删除操作也不太友好,因为这些操作可能导致哈希冲突,进而影响索引的性能。 此外,MySQL还引入了自适应哈希索引的概念。自适应哈希索引是一种动态索引结构,它根据查询模式自动选择是否使用哈希索引自适应哈希索引可以根据实际查询情况动态地创建和删除哈希索引,以提高查询性能。但是,创建哈希索引也会消耗一定的资源,因此需要根据具体的衡量参数来决定是否打开或关闭自适应哈希索引。 总结来说,MySQL哈希索引是一种用于加快数据检索速度的索引结构,它具有快速的搜索效率和较低的磁盘IO开销。然而,哈希索引只适用于等值查询,并且对于频繁的插入和删除操作不太友好。自适应哈希索引是一种动态索引结构,可以根据查询模式自动选择是否使用哈希索引,以提高查询性能。 #### 引用[.reference_title] - *1* *2* *3* [Mysql哈希索引](https://blog.csdn.net/Reggie0202/article/details/122238967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值