mysql(三)InnoDB之自适应hash索引

news/2024/7/9 22:53:39

目录

  • 前言
  • 自适应哈希索引 (Adaptive Hash Index, AHI)
    • 既然是哈希,key 是什么,value 是什么?
    • 为啥叫 “自适应 (adaptive)****” 哈希索引?
    • 系统会不会判断失误,是不是一定能加速?
  • 创建自定义的hash索引
    • 思路
    • 示例
      • 如何处理hash冲突

前言

InnoDB 用户无法手动创建哈希索引,如果从这一层面来说,InnoDB 不支持哈希索引,但是InnoDB 会自调优 (self-tuning),如果判定建立自适应哈希索引 (Adaptive Hash Index, AHI),能够提升查询效率,InnoDB 自己会建立相关哈希索引,如果从这一层来说,InnoDB 是支持哈希索引的

自适应哈希索引 (Adaptive Hash Index, AHI)

新建一张表

CREATE TABLE `user`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NULL,
  `sex` char(4) NULL,
  `flag` char(4) NULL,
  PRIMARY KEY (`id`),
  INDEX `name`(`name`) USING BTREE
);

id 是主键,name 建了普通索引。

在表中插入四条记录:

  • 1, shenjian, m, A

  • 3, zhangsan, m, A

  • 5, lisi, m, A

  • 9, wangwu, f, B

在这里插入图片描述
如上图,通过前序知识,容易知道 InnoDB 在主键 id 上会建立聚集索引 (Clustered Index),叶子存储记录本身,在 name 上会建立普通索引 (Secondary Index),叶子存储主键值。

发起主键 id 查询时,能够通过聚集索引,直接定位到行记录。
在这里插入图片描述

select * from t where name='ls'

发起普通索引查询时:

  1. 会先从普通索引查询出主键(上图右边);

  2. 再由主键,从聚集索引上二次遍历定位到记录(上图左边)。

不管聚集索引还是普通索引,记录定位的寻路路径 (Search Path) 都很长。

在 MySQL 运行的过程中,如果 InnoDB 发现,有很多 SQL 存在这类很长的寻路,并且有很多 SQL 会命中相同的页面 (page),InnoDB 会在自己的内存缓冲区 (Buffer) 里,开辟一块区域,建立自适应哈希所有 AHI,以加速查询。
在这里插入图片描述
从这个层面上来说,InnoDB 的自使用哈希索引,更像 “索引的索引”,毕竟其目的是为了加速索引寻路。

既然是哈希,key 是什么,value 是什么?

key 是索引键值(或者键值前缀),value 是索引记录页面位置。

为啥叫 “自适应 (adaptive)****” 哈希索引?

系统自己判断 “应该可以加速查询” 而建立的,不需要用户手动建立,故称“自适应”。

系统会不会判断失误,是不是一定能加速?

不是一定能加速,有时候会误判。

当业务场景为下面几种情况时:

  • 很多单行记录查询(例如 passport,用户中心等业务)
  • 索引范围查询(此时 AHI 可以快速定位首行记录)
  • 所有记录内存能放得下

AHI 往往是有效的。当业务有大量 like 或者 join,AHI 的维护反而可能成为负担,降低系统效率,此时可以手动关闭 AHI 功能

创建自定义的hash索引

如果存储引擎不支持hash索引,则可以模拟像InnoDB一样创建hash索引,这样可以得到hash索引带来的便利,如只需要 很小的索引就可以为超长的键创建索引

思路

在B-Tree的基础上创建一个伪hash索引,这和真正的hash索引不是一回事,因为还是使用B-Tree进行查找,但是它使用hash值而不是键本身进行索引查找。我们需要做的就是在查询的WHERE字句中手动指定使用hash函数

示例

此时我么新建一张表,需要存储大量的URL,并且根据URL进行搜索查找。如果使用B-tree来存储URL,存储的内容就会很大,因为URL本身都很长。

新建一张表

create table pseudohash(
id int UNSIGNED not null auto_increment,
url VARCHAR(255) not null,
url_crc int UNSIGNED not null DEFAULT 0,
PRIMARY KEY(id)
) 

然后创建触发器

CREATE TRIGGER pseudohash_crc_ins BEFORE INSERT ON pseudohash FOR EACH ROW
BEGIN	
	SET NEW.url_crc = CRC32(
	NEW.url);
	end;
	
	
CREATE TRIGGER pseudohash_crc_upd BEFORE UPDATE ON pseudohash FOR EACH ROW
BEGIN	
	SET NEW.url_crc = CRC32(
	NEW.url);
	end;

插入数据
在这里插入图片描述

一般情况,是在url建索引查询

select id from pseudohash where url ='www.baidu.com123217'

但是我们删除了url上面的索引,对url_crc使用CRC32做hash,就可以使用下面的方式进行查询

select id from pseudohash where url='www.baidu.com123217' and url_crc = CRC32('www.baidu.com123217')

这样做的性能就会很高,因为MySQL优化器会使用这个选择性很高而体积很小的基于url_crc列的索引来完成查找。即使有多个记录有相同的索引值,朝招仍然很快,只需要根据hash值做快速的整数比较就能找到索引条目,然后一一比较返回对应的行。但是这样实现的缺陷就是需要维护hash值。可以手动维护,也可选择使用触发器

如果采用这种方式,最好不要使用SHA1()和MD5()作为hash函数。因为这两个函数计算出来的hash值是非常长的字符串,会浪费大量空间,比较时也会更慢。SHA1()和MD5()是强加密函数,设计的目标是最大限度的消除冲突,但这里并不需要这样高德要求。简单的hash函数的冲突在一个可以接受的范围,同时又能提供更好的性能。

如果表非常大,CRC32()会出现大量的hash冲突,则可以考虑自己实现一个简单的64位hash函数

如何处理hash冲突

查询的时候,必须得是如下

select id from pseudohash where url='www.baidu.com123217' and url_crc = CRC32('www.baidu.com123217')

仅仅是如下的查询

select id from pseudohash where  url_crc = CRC32('www.baidu.com123217')

当发生hash冲突的时候,是无法正确工作的

参考:

https://zhuanlan.zhihu.com/p/339957841


http://www.niftyadmin.cn/n/4556957.html

相关文章

Java 多线程学习随笔

博文内容中字符过多,拒绝显示 转载于:https://www.cnblogs.com/zhangrj9/p/9872633.html

怎么才可以学好C语言

||| 先把基本语法熟悉后 用你学的语言实现一些简单的算法 基本语法熟练后 常看别人写的代码.多练就行了.有什么不会的问我.QQ107416106 多写程序...只有这样 ||| 先编200个小程序 ||| 先只是将书上的源程序 照打进 编译器里 运行 然后对其中的你不明白的地方进行改动 看运行的结…

redis典型使用场景

1.缓存功能 下图是比较典型的缓存使用场景,其中Redis作为缓存层,MySQL作为缓存层,绝大部分请求的数据都是从Redis中获取,由于Redis具有支撑高并发的特性,所以缓存通常起到加速读写和降低后端压力的作用。 2. 计数 许多…

Word Amalgamation

链接 [https://vjudge.net/contest/212939#problem/C] 题意 给你个字典,字典包含若干个单词; 再给你若干个单词,让你输出跟这个单词有相同的字母的字典里的单词(不考虑顺序) 分析 STL set的应用以及next_permutation的应用 用set保存字典里的…

要考3级C了 谢谢哈~ 拜托了 请问谁有VC++6.0的英文版下载地址

searchVC%2B%2B&suffix&restype-1&id2 您去看下 这里很多资源 里面有英文版的 VC6.0(英文版)下载: ftp://fzskydown:down61.152.92.98//VC60EN.iso (复制到迅雷中下载) VC6.0 SP6(英文版)下载 http://download.microsoft.com/download/1/9/f/19fe4660-5792-4683-99…

摘录的关于代码维护性的文章片段

https://blog.csdn.net/zhanghuiqi205/article/details/80332729 检查代码可读性和可维护性: 如果代码的可读性强,那么维护起来也就方便很多;一个好的代码规范和编码风格会节省大家对代码的理解时间,减少维护成本;虽然…

Redis的五种数据类型详解

type命令实际返回的就是当前键的数据结构类型,他们分别是:String、hash、list、set(集合)、zset(有序集合),但这些只是Redis对外的数据结构。 实际上每一种数据结构都有自己底层的内部编码实现,…

B/S 与 C/S 相比各有何优缺点

相对于C/S结构 MYIE等)运行软件 如Internet Explorer 而客户端采用浏览器(Browse 就是只安装维护一个服务器(Server) B/S结构软件的好处 何谓B/S结构 1.首先 但与B/S相比 有了很大的进步 尽管C/S结构相对于更早的文件服务器来说 即…