When conversions from string to floating-point and from integer to floating-point occur, they do not necessarily occur the same way. The integer may be converted to floating-point by the CPU, whereas the string is converted digit by digit in an operation that involves floating-point multiplications. Also, results can be affected by factors such as computer architecture or the compiler version or optimization level. One way to avoid such problems is to use CAST() so that a value is not converted implicitly to a float-point number.
这种不同类型的比较,由于需要 cast(无论是显式的 cast as unsigned,还是隐式的浮点转换),都会导致索引失效。
同样是上面的 MySQL 文档,您可以看到:
For comparisons of a string column with a number, MySQL cannot use an index on the column to look up the value quickly. If str_col is an indexed string column, the index cannot be used when performing the lookup in the following statement:
SELECT * FROM tbl_name WHERE str_col=1;
The reason for this is that there are many different strings that may convert to the value 1 , such as '1' , ' 1' , or '1a' .
对应到 TiDB 中,即便我们在 bill_number 上添加一个索引,比如叫做 b_idx,然后执行查询 “select * from t_test_decimal use index(b_idx) where bill_number = 766953682666393600;”,您可以看到如下的 explain 结果:
tidb> explain select * from t_test_decimal use index(b_idx) where bill_number = 766953682666393600;
+-------------------------+---------+-----------+------------------------------------------------+------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+-------------------------+---------+-----------+------------------------------------------------+------------------------------------------------------------------+
| IndexReader_7 | 3.20 | root | | index:Selection_6 |
| └─Selection_6 | 3.20 | cop[tikv] | | eq(cast(test.t_test_decimal.bill_number), 7.669536826663936e+17) |
| └─IndexFullScan_5 | 4.00 | cop[tikv] | table:t_test_decimal, index:b_idx(bill_number) | keep order:false, stats:pseudo |
+-------------------------+---------+-----------+------------------------------------------------+------------------------------------------------------------------+
3 rows in set (0.00 sec)
如上,在强制使用 b_idx 的情况下,TiDB 仍然要做一次 Full Index Scan,然后执行 cast bill_number 与 766953682666393600 的比较过滤。可以认为索引并没有起到作用。