Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题

作者:Jeff、yuan 时间:2024-01-22 04:07:47 

背景

  • 在一次进行SQl查询时,我试着对where条件中vachar类型的字段去掉单引号查询,这个时候发现这条本应该很快的语句竟然很慢。这个varchar字段有一个复合索引。其中的总条数有58989,甚至不加单引号查出来的数据不是我们想要的数据。

  • 使用的是mysql 5.6版本,innoDB引擎 实际情况如下

下面我们来看一下执行的结果

Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题

在上面的描述中我们还得注意就是,你的where条件的字符串不加单引号必须是全数字。不然就会报错

Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题

还有可能查出来的数据不是我们想要的数据。如下图

Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题

分析

  1. 从执行结果来看,使用了单引号的走了对应的索引。没有使用单引号的没有走索引,进行了全表扫描。

  2. 为什么会这样呢? mysql的优化器怎么不直接进行类型转换呢?

  • 在SQL语句中单引号的引入也就是代表这个类型是字符串数据类型CHAR, VARCHAR, BINARY, VARBINARY, BLOB, TEXT, ENUM,和 SET。。

  • 不加单引号也就代表这是一个字符串之外的类型,如int,bigDecimal类型等

  • 如果给一串有字幕和特殊符号的字符串不加单引号,后果就是类型转换失败导致SQl不能执行。

如上图所述:


1054 - Unknown column '000w1993521' in 'where clause', Time: 0.008000s

我们先来看一下一条SQL的执行过程

Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题

(网图)

  • 我们先得出结论:如果对索引字段做函数操作(本例是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. 产生条件
当操作符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。则会发生转换隐式
发生隐式转换的条件:

  1. 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换

  2. 两个参数都是字符串,会按照字符串来比较,不做类型转换

  3. 两个参数都是整数,按照整数来比较,不做类型转换

  4. 十六进制的值和非数字做比较时,会被当做二进制串

  5. 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp

  6. 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较

  7. 所有其他情况下,两个参数都会被转换为浮点数再进行比较

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

来源:https://blog.csdn.net/weixin_40413961/article/details/110743406

标签:Mysql,5.6,隐式转换,索引失效
0
投稿

猜你喜欢

  • python 协程 gevent原理与用法分析

    2021-10-12 23:36:19
  • asp怎么实现中文字符串按声母检索

    2010-05-16 21:19:00
  • php通过隐藏表单控件获取到前两个页面的url

    2023-11-16 04:00:08
  • 使用Django开发简单接口实现文章增删改查

    2023-02-12 22:29:37
  • js事件委托和事件代理案例分享

    2024-04-28 09:51:31
  • js实现砖头在页面拖拉效果

    2024-05-22 10:40:24
  • sqlserver分页查询处理方法小结

    2024-01-13 19:50:23
  • Python JWT认证与pyjwt包详细介绍

    2022-04-28 23:52:31
  • CSS控制鼠标样式变换方法

    2007-11-17 07:58:00
  • win32com操作word之Application&Documents接口学习

    2021-03-01 13:30:34
  • laravel yajra插件 datatable的使用详解

    2023-11-18 20:05:06
  • Golang map如何生成有序的json数据详解

    2024-05-09 09:47:45
  • 使用Python实现BT种子和磁力链接的相互转换

    2022-12-21 04:33:25
  • Pytorch中torch.flatten()和torch.nn.Flatten()实例详解

    2021-09-15 06:39:43
  • 使用python判断jpeg图片的完整性实例

    2021-10-05 19:50:09
  • Study jQuery in a Simplified Way

    2010-01-30 12:55:00
  • mysql之TIMESTAMP(时间戳)用法详解

    2024-01-13 16:06:42
  • Python list sort方法的具体使用

    2023-01-14 22:27:46
  • npm qs模块使用详解

    2024-04-25 13:11:14
  • VSCode 使用Settings Sync同步配置(最新版教程,非常简单)

    2022-10-17 08:50:47
  • asp之家 网络编程 m.aspxhome.com