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索引带来的巨大性能提升----[真相篇]的更多相关文章
- Mysql 自定义HASH索引带来的巨大性能提升----[挖坑篇]
有这样一个业务场景,需要在2个表里比较存在于A表,不存在于B表的数据.表结构如下: T_SETTINGS_BACKUP | CREATE TABLE `T_SETTINGS_BACKUP` ( `FI ...
- Mysql 自定义HASH索引带来的巨大性能提升
有这样一个业务场景,需要在2个表里比较存在于A表,不存在于B表的数据.表结构如下: T_SETTINGS_BACKUP | CREATE TABLE `T_SETTINGS_BACKUP` ( `FI ...
- MySQL 8.0 —— CATS事务调度算法的性能提升
原文地址:https://mysqlserverteam.com/contention-aware-transaction-scheduling-arriving-in-innodb-to-boost ...
- SQL优化系列(三)- 用最少的索引获得最大的性能提升
从全局出发优化索引 对于高负载的数据库,如何创建最少的索引,让数据库的整体性能提高呢?例如,对于100 条SQL语句,如何创建最佳的5条索引? SQL自动优化工具SQL Tuning Expert P ...
- MySQL系列(六)--索引优化
在进行数据库查询的时候,索引是非常重要的,当然前提是达到一定的数据量.索引就像字典一样,通过偏旁部首来快速定位,而不是一页页 的慢慢找. 索引依赖存储引擎层实现,所以支持的索引类型和存储引擎相关,同一 ...
- InnoDB关键特性之自适应hash索引
一.索引的资源消耗分析 1.索引三大特点 1.小:只在一个到多个列建立索引 2.有序:可以快速定位终点 3.有棵树:可以定位起点,树高一般小于等于3 2.索引的资源消耗点 1.树的高度,顺序访问索引的 ...
- 数据库索引------B-Tree 索引和 Hash 索引的对比
对于 B-tree 和 hash 数据结构的理解能够有助于预测不同存储引擎下使用不同索引的查询性能的差异,尤其是那些允许你选择 B-tree 或者 hash 索引的内存存储引擎. B-Tree 索引的 ...
- B-Tree 索引和 Hash 索引的对照
对于 B-tree 和 hash 数据结构的理解可以有助于预測不同存储引擎下使用不同索引的查询性能的差异.尤其是那些同意你选择 B-tree 或者 hash 索引的内存存储引擎. B-Tree 索引的 ...
- Innodb关键特性之自适用Hash索引
一.索引的资源消耗分析 1.索引三大特点 1.小:只在一个到多个列建立索引 2.有序:可以快速定位终点 3.有棵树:可以定位起点,树高一般小于等于3 2.索引的资源消耗点 1.树的高度,顺序访问索引的 ...
随机推荐
- banner秒杀
永远显示 未开始/进行中(需要用到两个for循环,第一个我没有想到,诗詹帮我写的) function timeList(){ myTime = new Date().getTime() var ite ...
- ADO.NET 增、删、改、查
ADO.NET:数据访问技术 就是将C#和MSSQL连接起来的一个纽带 可以通过ADO.NET将内存中的临时数据写入到数据库中也可以将数据库中的数据提取到内存中供程序调用 所有数据访问技术的基础 连接 ...
- java写hadoop全局排序
前言: 一直不会用java,都是streaming的方式用C或者python写mapper或者reducer的可执行程序.但是有些情况,如全排序等等用streaming的方式往往不好处理,于是乎用原生 ...
- PHP分页做法
1.分页封装类 <?php /** file: page.class.php 完美分页类 Page */ class Page { private $total; //数据表中总记录数 priv ...
- sqlserver存储过程批量插入数据
在系统中经常会遇到向数据库中批量插入数据情况,存储过程中没有数组,只有通过字符串分割循环插入,下面是一个本人研究的一个例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 c ...
- css3隔行变换色实现示例
<style>#list1 li:nth-of-type(odd){ background:#00ccff;}/*奇数行*/ #list1 li:nth-of-type(even){ ba ...
- UML学习笔记1
UML概述:是一种为面向对象软件设计提供的建模语言. 构成:事物things关系relationshs图diagrams UML事物:构件事物 行为事物 分组事物 注释事物 UML关系:依赖depen ...
- Mark一下,一上午就这么过去了,关于客户端连接oracle10G的问题
Mark一下,一上午就这么过去了,关于客户端连接oracle10G的问题 正常的客户端PLSQL和Navicat都可以正常连接Oracle(局域网内),但代码生成器和VS2015死活连不上,在网上找了 ...
- Oracle 11gR2 安装教学
官方网址:http://www.oracle.com/index.html 选择你的"操作系统"下载 例如: 环境:x64 Win2012 R2 Oracle:win64_11gR ...
- 不能将 Null 值赋给类型为 (不可为 null 的值类型)的成员。解决方法
一般代码没有错,是对应的数据库里有的字段是NULL,不是主键,主键肯定不会是NULL的.是其他字段. 把这些列的NULL赋值.