mysql创建自定义伪hash索引

电玩女神 2023-06-28 06:21 36阅读 0赞

innodb存储引擎中使用hash索引的原因:(innodb中无法使用hash索引,只由btree索引)

  1. -- 创建资源表
  2. CREATE TABLE `my_resource` (
  3. `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主键',
  4. `resource_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源名称',
  5. `type` int(2) NOT NULL DEFAULT 0 COMMENT '资源类型 0其他 1视频 2文件',
  6. `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源地址',
  7. PRIMARY KEY (`id`) USING BTREE
  8. ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  9. -- url字段上创建索引,用于检索
  10. create index idx_url on my_resource (url asc);
  11. -- 新增数据
  12. insert into my_resource (resource_name,type,url) values('庆余年_1',1,'https://v.qq.com/x/cover/rjae621myqca41h/Cz4BRyhUY3.html');
  13. insert into my_resource (resource_name,type,url) values('庆余年_2',1,'https://v.qq.com/x/cover/rjae621myqca41h/tlTt4CiBc1.html');
  14. insert into my_resource (resource_name,type,url) values('庆余年_3',1,'https://v.qq.com/x/cover/rjae621myqca41h/QdTUsz40Cb.html');
  15. insert into my_resource (resource_name,type,url) values('庆余年_4',1,'https://v.qq.com/x/cover/rjae621myqca41h/dFdlXmOd9n.html');
  16. insert into my_resource (resource_name,type,url) values('庆余年_5',1,'https://v.qq.com/x/cover/rjae621myqca41h/TsvFR6b8wg.html');
  17. insert into my_resource (resource_name,type,url) values('庆余年_6',1,'https://v.qq.com/x/cover/rjae621myqca41h/YgWeaPrYpc.html');
  18. -- 查询执行计划
  19. explain select url from my_resource order by url ;

20200107194557449.jpg

从执行计划中可以看出,key中用到了索引idx_url,但是索引长度为767,而索引优化中,索引长度是越短越好,

原因:索引长度直接影响索引文件的大小,影响增删改的速度,并间接影响查询速度(占用内存多).
针对列中的值,从左往右截取部分,来建索引
1: 截的越短, 重复度越高,区分度越小, 索引效果越不好
2: 截的越长, 重复度越低,区分度越高, 索引效果越好,但带来的影响也越大—增删改变慢,并间影响查询速度.
所以, 要在 区分度 + 长度 两者上,取得一个平衡.

解决方法:截取不同长度,并测试其区分度

  1. -- 截取url字段长度,从1开始截取,计算字符前缀没有重复的字符占全部数据的比例
  2. select count(distinct right(url,15))/count(*) from my_resource;

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIyMDQ5Nzcz_size_16_color_FFFFFF_t_70

区分百分比达到1是最最理想的

自定义伪hash索引:(核心内容)

前提

在数据类型上考虑,自然想到,是不是可以把记录比较字段从字符串的比较,改成数字的比较?
这是个优化的方向。在计算机里底层数据都是01010这样,只需要把数字换算成0101就可以做等值比较了,但是变成字符,需要先去字符编码表找到字符对应的数字,在把数字换算成0101,这里多出一步查找操作。另一方面字符占用的空间比数字要大很多,一个页内能存下的item条目比数字的要少,这会导致更多的数据页读取。

根据这个方向,尝试使用自定义HASH索引,常见的HASH函数有MD5,crc32,sha1等,只有crc32哈希之后的值的数字型的。

20200107195525695.png

伪hash索引创建操作:

1、在表里加个字段记录hash之后的值,并对这个字段加上索引(innodb的btree索引)。

  1. -- 添加 url的伪hash索引值存储字段 bigint类型
  2. ALTER TABLE my_resource ADD COLUMN `url_crc32` bigint(10) NOT NULL COMMENT 'url的伪hash索引值存储字段' AFTER `url`;
  3. -- 创建该字段索引
  4. create index idx_url_crc32 on my_resource (url_crc32 asc);
  5. --删除 url的索引
  6. drop index idx_url on my_resource;

2、创建触发器

  1. delimiter $$
  2. CREATE TRIGGER my_resource_url_crc32_trigger BEFORE INSERT ON my_resource FOR EACH ROW
  3. BEGIN
  4. SET NEW.url_crc32 = crc32(NEW.url);-- url通过crc32计算后将结果赋值给url_crc
  5. END; $$
  6. delimiter ;

3、新增数据,查看结果

20200107203129226.png

4、查看执行计划

  1. explain select url_crc32 from my_resource order by url_crc32;

key_len长度为8,打完收工

20200107203741502.png

4、hash索引的缺点

1)hash不能处理范围比较,只能处理等值比较。

2)hash不能做排序,hash出来的结果是随机分布的。(上例只是为了看效果,切勿做排序)

3)hash不支持部分索引,如index a(10)就不支持。

4)hash无法覆盖索引

5)hash有碰撞,碰撞得比较厉害时,处理碰撞的代价就比较高。

发表评论

表情:
评论列表 (有 0 条评论,36人围观)

还没有评论,来说两句吧...

相关阅读

    相关 MySql--索引定义函数

      在MySql中,如果数据表中数据量非常庞大的时候,查询某条记录会非常的浪费时间,鉴于此,MySql提供了一种提高查询效率的工具——索引,有了索引查询速率大大的提高了。