Mysql 自定义HASH索引带来的巨大性能提升----[真相篇]

推倒重来

俗话说no zuo no die why you try,这时候我又忍不住zuo了,吭哧吭哧的把解决过程发上博客,向全世界宣布,哥又搞定个难题。

剧情的发展往往是看起来主角完全掌握了局势的情况下,会突然跳出来一个很牛的反面人物,然后搞得主角很惨,搞的过程中主角开始小宇宙爆发,然后逆袭。这次也不例外。踢场子的人该出现了

一顿狂侃之后,发现我原来牛逼的分析,完全经不起推敲。几个问题

1)  在未做HASH索引之前,为什么大表的ROWS那么大,相当于全表扫描

2)  既然SN是唯一索引,那么为什么关联查询的时候不能准确定位?

3)  在做了HASH索引之后,关联查询只是换了不同的判断字段,就能做到rows=1,这是为何?

在这里阐释一下通过索引是怎样做JOIN操作和索引定位数据的

在关系数据库里,常见的处理JOIN的方法有几种:NESTED LOOP,HASH JOIN,SORT MERGE JOIN,各种JOIN有什么差别WIKI上有详细的介绍。MYSQL实现的是NESTED LOOP,俗称嵌套循环。

结合前面的查询来看,JOIN的关联字段是FDEVICE和FSN,查询的过程是这样的

FOR FDEVICE IN A:

FOR FSN IN B:

IF A.FDEVICE=B.FSN:

Store result into record buffer

Send result

嵌套循环就是这么实现的。

在IF A.FDEVICE=B.FSN:这一步,对B表数据进行比较时,B的FSH上有索引,先通过索引查找,得到主键ID,然后根据主键ID获取整行记录的具体值。

在这个案例里,B的FSN是唯一值,A的FDEVICE在B表里,要么不存在,要么只有一条记录与之匹配,不会有第三种情况发生。

在未做自定义hash索引之前的SQL,应该就是这个执行过程才对,hash一次后,再在hash 字段做个索引,其实只是换了个实现途径,并没有解释为什么之前的方法为什么会全表扫描,潜伏在表象下的真相并不如此。

回到事件的原点,为什么最开始的那个SQL的执行计划里,ROWS等于全表,而走自定义hash索引后的rows=1?通过对索引原理的分析,它只要是用了索引,rows必然是1,如果没有用到索引,那么key这一列又必然是NULL,正是这个矛盾,从一开始就把我引向歧途,误认为是索引本身的问题,然后想当然的弄了个hash索引,然后误打误撞把问题解决。

意外发现

首先要把一切不可能的事实都排除,那其余的,不管多么离奇,多么难以置信,也必然是无可辩驳的事实                     夏洛克.福尔摩斯

在这个案例里,不可能的事实就是,嵌套循环的执行过程不会变,索引查找数据的过程不会变。那么还剩下什么?

1)  看到的ROWS=490W是假象  2)看到的key=sn是假象

从执行效率来看,ROWS=490W是真的,要么不会这么慢,那么KEY=SN是假的就有可能,看起来用到了索引,事实上索引完全没有起作用。

再次把视线集中到两个关联查询的表结构上,发现一个很不起眼的异常现象:`sn` varchar(20) CHARACTER SET utf8 。这个字段的字符集是utf8的,而与之关联的字段的字符集是utf8mb4的,两个不同的字段比较,是不是会引起索引失效?

很快实验结果就出来了,而这次,才是事件背后的真相。

当两个关联字段的字符集相同时,索引运行如预期。

当我只有一个锤子时,很自然的把任何问题都看成钉子,先入为主的思维使一些简单而重要的细节被忽略,而这些线索能指引我们找出事情的真相。走完一圈弯路蓦然回首,其实那个苦苦寻觅的完美世界就在眼前,只是我们被偏见和愚昧蒙蔽了双眼。

Mysql 自定义HASH索引带来的巨大性能提升----[真相篇]

时间: 2024-12-18 05:16:18

Mysql 自定义HASH索引带来的巨大性能提升----[真相篇]的相关文章

Mysql 自定义HASH索引带来的巨大性能提升

有这样一个业务场景,需要在2个表里比较存在于A表,不存在于B表的数据.表结构如下: T_SETTINGS_BACKUP | CREATE TABLE `T_SETTINGS_BACKUP` ( `FID` bigint(20) NOT NULL AUTO_INCREMENT, `FUSERID` bigint(20) NOT NULL COMMENT '用户ID', `FDEVICE` varchar(64) NOT NULL DEFAULT '' COMMENT '用户设备号(SN)', `F

长文本字段做自定义HASH索引

当要做URL匹配的时候,URL长度比较长,如果做文本索引,索引长度会很大, 用URL做64位HASH INT 索引长度才8个字节 function crcInt64($str) {     return ('0x' . hash('crc32', $str) . hash('crc32b', $str)) + 0; } 返回64位的INT 值... 数据库用 bigint 字段存储,做索引性能比URL做索引高好多倍.. 注意: mysql bigint 有个坑. 用bigint 的时候,在数据连

B-Tree 索引和 Hash 索引的对比

对于 B-tree 和 hash 数据结构的理解能够有助于预测不同存储引擎下使用不同索引的查询性能的差异,尤其是那些允许你选择 B-tree 或者 hash 索引的内存存储引擎. B-Tree 索引的特点 B-tree 索引可以用于使用 =, >, >=, <, <= 或者 BETWEEN 运算符的列比较.如果 LIKE 的参数是一个没有以通配符起始的常量字符串的话也可以使用这种索引.比如,以下 SELECT 语句就使用索引: SELECT * FROM tbl_name WHER

B-Tree 索引和 Hash 索引的对照

对于 B-tree 和 hash 数据结构的理解可以有助于预測不同存储引擎下使用不同索引的查询性能的差异.尤其是那些同意你选择 B-tree 或者 hash 索引的内存存储引擎. B-Tree 索引的特点 B-tree 索引可以用于使用 =, >, >=, <, <= 或者 BETWEEN 运算符的列比較.假设 LIKE 的參数是一个没有以通配符起始的常量字符串的话也可以使用这样的索引. 比方.下面 SELECT 语句就使用索引: SELECT * FROM tbl_name WH

InnoDB关键特性之自适应hash索引

一.索引的资源消耗分析 1.索引三大特点 1.小:只在一个到多个列建立索引 2.有序:可以快速定位终点 3.有棵树:可以定位起点,树高一般小于等于3 2.索引的资源消耗点 1.树的高度,顺序访问索引的数据页,索引就是在列上建立的,数据量非常小,在内存中: 2.数据之间跳着访问 1.索引往表上跳,可能需要访问表的数据页很多: 2.通过索引访问表,主键列和索引的有序度出现严重的不一致时,可能就会产生大量物理读: 资源消耗最厉害:通过索引访问多行,需要从表中取多行数据,如果无序的话,来回跳着找,跳着访

mysql btree与hash索引的适用场景和限制

btree索引: 如果没有特别指明类型,多半说的就是btree索引,它使用btree数据结构来存储数据,大多数mysql引擎都支持这种索引,archive引擎是一个例外,5.1之前这个引擎不支持任何索引,5.1开始才支持单列自增的索引.innodb使用b+tree=btree(btree已经不使用了) 存储引擎以不同的方式使用btree索引,性能也各不相同,各有优劣,如:myisam使用前缀压缩技术使得索引更小(但也可能导致连接表查询性能降低),但innodb则按照原数据格式进行存储,再如:my

MySQL的btree索引和hash索引的区别

Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引. 可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢?任何事物都是有两面性的,Hash 索引也一样,虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以

MySQL索引类型 btree索引和hash索引的区别

来源一 Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引. 可 能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢?任何事物都是有两面性的,Hash 索引也一样,虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊端

mysql Hash索引和BTree索引区别

Hash仅支持=.>.>=.<.<=.between.BTree可以支持like模糊查询 索引是帮助mysql获取数据的数据结构.最常见的索引是Btree索引和Hash索引. 不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引:而Mermory默认的索引是Hash索引. 我们在mysql中常用两种索引算法BTree和Hash,两种算法检索方式不一样,对查询的作用也不一样. 一.BTree BTree索引是最常用的mysql数据库索引算法,因为它不仅