TL;DR:函数作用于表字段时,索引会失效。
== 具体情况 ==
Indexes如下:
SQL如下:
explain select *
from accounting_status_flow_tab_00000000
WHERE ( client_no = 6848134000 and loan_no = 0119324345936016261000 )
order by modify_date DESC limit 400;
很明显,应该走idx_loan_no_accounting_date索引,结果走了全表扫描:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | accounting_status_flow_tab_00000000 | null | ALL | idx_loan_no_accounting_date | null | null | null | 120 | 1 | Using where; Using filesort |
查看日志,报错:
Cannot use ref access on index 'idx_loan_no_accounting_date' due to type or collation conversion on field 'loan_no'
后来,改成下面的SQL就好了:
explain select *
from accounting_status_flow_tab_00000000
WHERE ( client_no = '6848134000' and loan_no = '0119324345936016261000' )
order by modify_date DESC limit 400;
原来,是因为 client_no、loan_no 没有用字符串(原类型)的形式。
MySQL 的策略是将字符串转换为数字之后再比较,而如果函数作用于表字段时,索引会失效。