`

mysql隐式转换导致查询语句不能走索引分析

阅读更多

        如下两条SQL语句,一个不走索引,一个走索引。


        在这里,为什么第一条语句未加单引号就不走索引,而第二条加单引号的就走索引呢?

原因是第一条语句由于类型不匹配,MySQL会做隐式的类型转换,都将其转换为浮点数在比较;而第二条语句因为类型一致,不会转浮点数,就是字符串之间的比较,所以就能正常走索引。

一.进一步了解隐式转换

对于第一种情况:

        比如where string = 1;需要将索引中的字符串转换成浮点数,但是由于'1','1','1a'都会比转化成1,故MySQL无法使用索引只能进行全表扫描,故造成了慢查询的产生。

        这里并不是因为字符串字段值转换成了浮点数?而'1',' 1','1a'转换成1,是整数,类型不匹配导致只能进行全表扫描,而是因为都转换浮点数了,'1','1','1a'本来三个不同的值都是相同的值了,还是打破了有序的规则。

mysql> SELECT CAST('  1' AS SIGNED)=1;
+-------------------------+
| CAST('  1' AS SIGNED)=1 |
+-------------------------+
|                       1 |
+-------------------------+
1 row in set (0.00 sec)
 
mysql> SELECT CAST('  1a' AS SIGNED)=1;
+--------------------------+
| CAST('  1a' AS SIGNED)=1 |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set, 1 warning (0.00 sec)
 
mysql> SELECT CAST('1' AS SIGNED)=1;
+-----------------------+
| CAST('1' AS SIGNED)=1 |
+-----------------------+
|                     1 |
+-----------------------+
1 row in set (0.00 sec)

        同时需要注意一点,由于都会转换成浮点数进行比较,而浮点数只有53bit,故当超过最大值的时候,比较会出现问题。

对于第二种情况:

        由于索引建立在int的基础上,而将纯数字的字符串可以百分百转换成数字,故可以使用到索引,虽然也会进行一定的转换,消耗一定的资源,但是最终仍然使用了索引,不会产生慢查询。

mysql> select CAST( '30' as SIGNED) = 30;
+----------------------------+
| CAST( '30' as SIGNED) = 30 |
+----------------------------+
|                          1 |
+----------------------------+
1 row in set (0.00 sec)

 

二.官方解释

        为什么一个小小的''为什么会有这么大的影响呢?根本原因是因为MySQL在对文本类型和数字类型进行比较的时候会进行隐式的类型转换。以下是5.5官方手册的说明:

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.
有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
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.
有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
In all other cases, the arguments are compared as floating-point (real) numbers.
所有其他情况下,两个参数都会被转换为浮点数再进行比较

        根据以上的说明,当where条件之后的值的类型和表结构不一致的时候,MySQL会做隐式的类型转换,都将其转换为浮点数在比较。

  • 大小: 94 KB
分享到:
评论

相关推荐

    mysql中or是否走索引详解

    7. **EXPLAIN分析**:通过`EXPLAIN`命令,我们可以分析查询计划,了解MySQL是如何处理`OR`语句的,这有助于找出潜在的优化点。 8. **统计信息与查询优化**:数据库的统计信息,如索引的选择性,对优化器的决策有很...

    mysql查询不走索引及解决方法

    mysql查询,通过explain 分析,没有利用到索引,查询效率不高等出现的问题。

    mysql面试题,涉及MySQL基础、MySQL索引、MySQL语句 MySQL进阶等方面,适用于初、中级开发人员

    MySQL 面试题知识点总结 MySQL 是一种关系型数据库管理系统,广泛应用于各种 Web ...如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换可能会导致索引失效。

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

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

    MySQL的or、in、union与索引优化

    这种方式允许MySQL自行决定如何优化查询过程,虽然相比直接使用`union all`会消耗更多的CPU资源用于查询优化,但这部分消耗是可以忽略不计的。实际上,这种方式更受程序员欢迎,因为它简洁明了,易于理解和维护。 #...

    MySQL前缀索引导致的慢查询分析总结

    当执行`SELECT * FROM rosterusers ORDER BY username LIMIT 10000, 3`这样的查询时,由于使用了前缀索引,MySQL无法直接利用索引来完成排序,因此选择了全表扫描并使用"filesort"外部排序算法,导致查询速度变慢。...

    MySQL Like模糊查询速度太慢如何解决

    MySQL中的LIKE操作符常用于执行模糊查询,但其性能表现往往取决于查询模式和索引的使用情况。在处理大量数据时,低效的LIKE查询可能导致显著的性能下降。以下是一些关于如何优化MySQL LIKE模糊查询的策略: 1. **...

    MySQL中因字段字符集不同导致索引不能命中的解决方法

    索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去...

    MySQL面试题MySQL面试题

    MySQL 语句执行步骤包括客户端请求、连接器、查询缓存、分析器、优化器、执行器等。连接器负责验证用户身份,给予权限。查询缓存如果存在缓存则直接返回,不存在则执行后续操作。分析器对 SQL 进行词法分析和语法...

    MySQL面试精选60题,附详细答案

    Server层按顺序执行SQL的步骤为:客户端请求 -> 连接器(验证用户身份,给予权限)查询缓存(存在缓存则直接返回,不存在则执行后续操作)分析器(对SQL进行词法分析和语法分析操作)优化器(主要对执行的SQL优化...

    MySQL面试题精选60道

    Server 层按顺序执行 SQL 的步骤为:客户端请求 -> 连接器(验证用户身份,给予权限)-> 查询缓存(存在缓存则直接返回,不存在则执行后续操作)-> 分析器(对 SQL 进行词法分析和语法分析操作)-> 优化器(主要对...

    一些比较常见的mysql面试题

    客户端请求 -> 连接器(验证用户身份,给予权限) -> 查询缓存(存在缓存则直接返回,不存在则执行后续操作) -> 分析器(对 SQL 进行词法分析和语法分析操作) -> 优化器(主要对执行的 SQL 优化选择最优的执行方案...

    MySQL Order By索引优化方法

    总之,理解`ORDER BY`和`GROUP BY`的索引优化策略,以及如何通过`EXPLAIN`分析查询计划,可以帮助我们有效地优化查询,避免不必要的`filesort`操作,从而提升MySQL数据库的性能。在设计索引时,应考虑查询语句的常见...

    mysql优化之like和=性能详析

    MySQL优化之LIKE与=性能详析 在数据库查询中,LIKE和=是两种常见的比较操作符,它们在功能上有着显著的区别,同时也涉及到性能优化的问题。...通过合理设计索引和优化查询语句,可以显著提升MySQL数据库的性能。

    Mysql慢查询优化方法及优化原则

    1、日期大小的比较,传到xml中的日期格式要符合’yyyy-MM-dd’,这样才能走索引,如:’yyyy’改为’yyyy-MM-dd’,’yyyy-MM’改为’yyyy-MM-dd’【这样MYSQL会转换为日期类型】 2、条件语句中无论是等于、还是大于...

    MYSQL中常用的强制性操作(例如强制索引)

    在MySQL数据库中,为了优化SQL查询性能,开发者有时需要对查询进行强制性的操作。...然而,过度使用或不恰当使用这些操作可能导致性能下降,因此应谨慎使用,并结合EXPLAIN分析和性能测试来确定最佳实践。

    为什么oracle有时不用索引来查找数据

    但是,通常不应擅自对数据字典表进行分析,因为这可能会导致死锁或其他性能问题。 6. **索引列是否为参数**:如果索引列是参数形式出现,那么在查询过程中可能无法使用索引。 7. **数据类型转换**:例如将字符型...

    MySQL 48道面试题及答案.docx

    慢查询的优化需要分析语句,是否加载了不必要的字段/数据,分析 SQI 执行句话,是否命中索引等。如果 SQL 很复杂,优化 SQL 结构,如果表数据量太大,考虑分表。 主键使用自增 ID 还是 UUID,这取决于系统的需求。...

Global site tag (gtag.js) - Google Analytics