隐式转换引起的sql慢查询实战记录

所属分类: 数据库 / 数据库其它 阅读数: 184
收藏 0 赞 0 分享

引言

实在很无语呀,遇到一个mysql隐式转换问题,问了周边的dba大拿该问题,他们居然反问我,你连这个也不知道?白白跟他们混了那么长   尼玛,我还真不知道。罪过罪过…. 

问题是这样的,一个字段叫task_id, 本身是varchar字符串类型,但是因为老系统时间太长了,我以为是int或者bigint,所以直接在代码写sql跑数据,结果等了好久就是没有反应,感觉要坏事呀。在mysql processlist里看到了该sql语句,直接kill掉。 该字段是有索引的,并且他的sql选择性很高,索引的价值也高。 但为什么这么慢?

分析问题

通过explain分析出了结果,当使用整型来查询字符串的字段会出现无法走索引的情况,看下面可以知道,key为NULL,没走索引,Rows是很大的数值,基本是全表扫描了。  当正常的用字符串查询字符串就很正常了,索引没问题,rows的值为1,这里说的是扫描聚簇索引的rows,而不是索引二级索引。

那么为什么会出现这问题?

下面是mysql官方给出的说法, 最后一条很重要,当在其他情况下,两个参数都会统一成 float 来比较。 居然新版的mysql在优化器层面已经做了一些调整规避这问题,但我自己的测试版本是mysql 5.6,阿里云用的也是5.7,都没有解决该问题。 看来是更高版本解决吧,这个待验证。

看完了官方解说,我们知道上面那一句慢查询sql,其实就相当于 where to_int(taskid) = 516006380 。当然直接用to_int是显示转换了,但是对比出来的效果是一致的。  不管是隐式转换,还是显示转换,速度能起来才怪。。。 因为mysql不支持函数索引。

# xiaorui.cc
 
If both arguments in a comparison operation are strings, they are compared as strings.
If both arguments are integers, they are compared as integers.
Hexadecimal values are treated as binary strings if not compared to a number.
If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point (real) numbers.

翻译为中文就是:

  • 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换
  • 两个参数都是字符串,会按照字符串来比较,不做类型转换
  • 两个参数都是整数,按照整数来比较,不做类型转换
  • 十六进制的值和非数字做比较时,会被当做二进制串
  • 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
  • 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
  • 所有其他情况下,两个参数都会被转换为浮点数再进行比较

总结

sql查询的时候,字段的类型要保持一致,不然会数据字段的隐式转换,继而出现慢查询。 还是那句废话,多看mysql的慢查询日志,有你想要的.

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

更多精彩内容其他人还在看

SQL中过滤条件放on和where中的区别详解

这篇文章主要给大家介绍了关于SQL中过滤条件放on和where中的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧
收藏 0 赞 0 分享

pymysql如何解决sql注入问题深入讲解

这篇文章主要给大家介绍了关于pymysql如何解决sql注入问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

关于sql注入的简要演示(入坑抛砖)

这篇文章主要介绍了关于sql注入的简要演示(入坑抛砖),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

SQL中一些小巧但常用的关键字小结

这篇文章主要给大家总结介绍了关于SQL中一些小巧但常用的关键字,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

谈谈数据库的字段设计的几个心得

今天小编就为大家分享一篇关于谈谈数据库的字段设计的几个心得,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

在windows系统下如何安装memcached的讲解

今天小编就为大家分享一篇关于在windows系统下如何安装memcached的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

数据库语言分类DDL、DCL、DML详解

今天小编就为大家分享一篇关于数据库语言分类DDL、DCL、DML详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

如何在一个千万级的数据库查询中提高查询的效率?

今天小编就为大家分享一篇关于如何在一个千万级的数据库查询中提高查询的效率?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

一篇文章带你了解数据库中JOIN的用法

这篇文章主要给大家介绍了关于数据库中JOIN的用法,文中通过示例代码介绍的非常详细,对大家学习或者使用数据库具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

一篇文章带你了解数据库中group by的用法

这篇文章主要给大家介绍了关于数据库中group by的法的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用数据库具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享
查看更多