mysql索引失效的几种情况(Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题)
mysql索引失效的几种情况
Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题背景
- 在一次进行sql查询时,我试着对where条件中vachar类型的字段去掉单引号查询,这个时候发现这条本应该很快的语句竟然很慢。这个varchar字段有一个复合索引。其中的总条数有58989,甚至不加单引号查出来的数据不是我们想要的数据。
- 使用的是mysql 5.6版本,innodb引擎 实际情况如下
下面我们来看一下执行的结果
在上面的描述中我们还得注意就是,你的where条件的字符串不加单引号必须是全数字。不然就会报错
还有可能查出来的数据不是我们想要的数据。如下图
分析
- 从执行结果来看,使用了单引号的走了对应的索引。没有使用单引号的没有走索引,进行了全表扫描。
- 为什么会这样呢? mysql的优化器怎么不直接进行类型转换呢?
- 在sql语句中单引号的引入也就是代表这个类型是字符串数据类型char, varchar, binary, varbinary, blob, text, enum,和 set。。
- 不加单引号也就代表这是一个字符串之外的类型,如int,bigdecimal类型等
- 如果给一串有字幕和特殊符号的字符串不加单引号,后果就是类型转换失败导致sql不能执行。
如上图所述:
|
1054 - unknown column '000w1993521' in 'where clause' , time : 0.008000s |
我们先来看一下一条sql的执行过程
(网图)
- 我们先得出结论:如果对索引字段做函数操作(本例是cast函数做了隐式的转换),可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。(https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html)
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l5awt0xu-1607244327891)(http://note.youdao.com/yws/res/23689/ce6f785994e6476d816b23787ce65217)]
- 意思也就是:请注意,如果您使用binary,cast()或convert()转换索引列,则mysql可能无法有效使用索引。
- 查出来的数据不准确,也是因为隐式转换,转换后导致数值类型不一样,导致不等变为相等。
隐式转换
1. 产生条件
当操作符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。则会发生转换隐式
发生隐式转换的条件:
- 两个参数至少有一个是 null 时,比较的结果也是 null,例外是使用 <=> 对两个 null 做比较时会返回 1,这两种情况都不需要做类型转换
- 两个参数都是字符串,会按照字符串来比较,不做类型转换
- 两个参数都是整数,按照整数来比较,不做类型转换
- 十六进制的值和非数字做比较时,会被当做二进制串
- 有一个参数是 timestamp 或 datetime,并且另外一个参数是常量,常量会被转换为 timestamp
- 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
- 所有其他情况下,两个参数都会被转换为浮点数再进行比较
2. 分析实际遇到的情况
1.那我们也就清楚了,上面我提出的例子是整数和字符串的比较,那就属于其他情况了。那我们就先来分析一下索引失效的原因
- 由于属于隐式转换的其他情况,所以对比值都得转换为浮点数进行比较
- 我们先将查询条件值进行转换为浮点数,再着将表的记录值也得进行转换,所以这个时候此前已经创建好的索引排序已经不能生效了。因为隐式转换(函数)已经改变了原来的值,所以说优化器在这里就直接不选用索引,直接使用全表扫描。
2.查询出不匹配的值(或者说是部分匹配的值),如上面的查询结果。这真得看看源码了,这也就是mysql的隐式转换规则。这里不就细分析了(因为没有查到相关的文档)
由于历史原因,需要兼容旧的设计,可以使用 mysql 的类型转换函数 cast 和 convert,来明确的进行转换。
总结
- 隐式转换和函数的使用会导致索引失效和select出的数据不准确
- 隐式转换的发生条件以及规则
- 隐式转换导致索引失效的具体原因,由于需要将对比值都要进行类型转换导致失效。
- 避免发生隐式类型转换,隐式转换的类型主要有字段类型不一致、in 参数包含多个类型、字符集类型或校对规则不一致等
参考
https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html
https://xiaomi-info.github.io/2019/12/24/mysql-implicit-conversion/
https://zhuanlan.zhihu.com/p/95170837
到此这篇关于mysql 5.6 “隐式转换”导致的索引失效和数据不准确的问题的文章就介绍到这了,更多相关mysql 5.6隐式转换导致的索引失效内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
原文链接:https://blog.csdn.net/weixin_40413961/article/details/110743406
- mysql删除表内所有数据(mysql 大表批量删除大量数据的实现方法)
- php添加数据到mysql数据库(PHP通过代码连接XAMPP数据库及MySQL数据库方法)
- mysql简单查询基本语句(详解MySQL 查询语句的执行过程)
- mpp数据库的客户端工具(xampp默认mysql数据库root密码的修改)
- mysql索引优化有哪些(MySQL如何基于Explain关键字优化索引功能)
- docker进入mysql查看路径(Docker 环境运行 Mysql 和开启 Binlog 配置主从同步的设置方法)
- 如何查看mysql执行计划(到底什么是Mysql执行计划?)
- mysql主键为什么用varchar(Mysql中varchar类型一些需要注意的地方)
- mysql定时任务
- mysql数据表的创建与管理(MySQL数据操作-DML语句的使用)
- mysql mvcc 底层原理(浅析MySQL - MVCC)
- 怎么查看mysql计划执行情况(详解 MySQL 执行计划)
- 设置mysql字符集语句(MySQL修改字符集的实战教程)
- mysql的存储性能优化(MySQL的查询缓存和Buffer Pool)
- mysql出现锁表的原因(导致MySQL做全表扫描的几种情况)
- mysql程序中判断select返回空值(解决MySQL读写分离导致insert后select不到数据的问题)
- 8月23日11时16分将迎处暑,逐渐进入气象意义上的秋天(8月23日11时16分将迎处暑)
- 花不语 下 如果重来一次的话,你还会这么选择吗(花不语下如果重来一次的话)
- 城市记忆之上海 最难忘的是老弄堂里的市井味道(城市记忆之上海)
- 太鸡贼了,这老小区轻松搞定了停车问题(这老小区轻松搞定了停车问题)
- 太鸡贼了,这老小区轻松搞定了停车问题(这老小区轻松搞定了停车问题)
- 节日我在岗|警景相融 平安相伴(节日我在岗警景相融)
热门推荐
- python里面的print怎么用(python中的print输出)
- svn迁移
- 云主机属于什么层次的云服务(什么是云?什么是云服务?什么是云主机?)
- 手机网站自适应的方法
- php单例设计方法(php设计模式之单例模式用法经典示例分析)
- 香港云服务器怎么那么火(如何选择便宜稳定的香港云服务器?)
- dedecms滚动代码(dedecms使用sql语句调用文章静态链接地址的方法)
- tomcat环境配置都正确无法运行(为什么我的tomcat启动不起来)
- docker从一个容器中退出来(Docker容器迁移到其他服务器的5种方法详解)
- python pandas 匹配值(python 使用pandas计算累积求和的方法)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9