MySQL implicit conversion causes the query statement to not go through the index analysis

        The following two SQL statements, one does not use the index, and the other uses the index.


        Here, why the first statement does not go to the index without single quotes, and the second statement with single quotes goes to the index?

The reason is that because the type of the first statement does not match, MySQL will do implicit type conversion and convert it to a floating-point number for comparison; while the second statement will not convert to a floating-point number because of the same type, that is, between strings. comparison, so you can walk the index normally.

1. Learn more about implicit conversions

For the first case:

        For example, where string = 1; the string in the index needs to be converted into a floating point number, but since '1', '1', and '1a' will all be converted into 1, MySQL cannot use the index and can only perform a full table scan, so Caused the generation of slow queries.

        Isn't this because the string field value is converted to a float? And '1', '1', '1a' are converted to 1, which are integers. The type mismatch leads to only a full table scan, but because they are all converted to floating-point numbers, '1', '1', '1a' Originally, the three different values ​​are all the same value, which still breaks the ordering rule.

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)

        At the same time, it should be noted that since they will be converted into floating-point numbers for comparison, and the floating-point numbers are only 53 bits, when the maximum value is exceeded, there will be problems in the comparison.

For the second case:

        Since the index is based on int, and the pure number string can be converted into a number 100%, so the index can be used, although a certain conversion will also be carried out, consuming a certain amount of resources, but the index is still used in the end. No slow queries are generated.

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

 

2. Official explanation

        Why does a small '' have such a big impact? The root cause is that MySQL performs implicit type conversions when comparing text types with numeric types. Here's what the 5.5 official manual says:

If both arguments in a comparison operation are strings, they are compared as strings.
Both parameters are strings and will be compared as strings without type conversion.
If both arguments are integers, they are compared as integers.
Both parameters are integers, and they are compared as integers without type conversion.
Hexadecimal values are treated as binary strings if not compared to a number.
Hexadecimal values ​​are treated as binary strings when compared to non-numeric values.
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.
One parameter is TIMESTAMP or DATETIME, and the other parameter is constant, constant will be converted to 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.
One parameter is of decimal type. If the other parameter is decimal or integer, the integer will be converted to decimal for comparison. If the other parameter is a floating-point number, the decimal will be converted to floating-point number for comparison.
In all other cases, the arguments are compared as floating-point (real) numbers.
In all other cases, both arguments are converted to floats and compared

        According to the above description, when the type of the value after the where condition is inconsistent with the table structure, MySQL will do implicit type conversion, and convert it to a floating-point number for comparison.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326507247&siteId=291194637