mysql有索引但是查询没有使用索引是什么问题
关键原因分析
-
索引选择性问题
- 如果
order_id
没有索引,即使insert_time
有索引,优化器可能认为先通过order_id
过滤数据更高效。但由于order_id
无索引,只能全表扫描后过滤。 - 即使
insert_time
有索引,如果满足insert_time >= '2024-02-26'
的数据量很大(如超过表总行数的 20%),优化器会认为全表扫描比回表更高效。
- 如果
-
缺乏复合索引
单列索引insert_time
仅能加速时间范围过滤,但无法同时优化order_id
的等值查询。若order_id
的过滤性(选择性)高,优化器更倾向于使用复合索引(order_id, insert_time)
。 -
统计信息不准确
表的统计信息(如索引基数)过期,导致优化器误判索引效果。可通过ANALYZE TABLE tb_oc_order;
更新统计信息。 -
隐式类型转换或函数调用
如果transaction_id
的字符集或排序规则与查询值不匹配,可能导致隐式转换,从而无法使用索引(需检查表结构)。
解决方案
-
为
transaction_id
添加索引
如果transaction_id
选择性高(如唯一或接近唯一),优先为其单独创建索引:ALTER TABLE tb_oc_order ADD INDEX idx_transaction_id (transaction_id);
-
创建复合索引
联合索引(transaction_id, insert_time)
可以同时优化两个条件:ALTER TABLE tb_oc_order ADD INDEX idx_trans_insert (transaction_id, insert_time);
- 优势:先通过
transaction_id
快速定位少量行,再按insert_time
过滤,效率更高。
- 优势:先通过
-
强制使用索引(谨慎使用)
通过FORCE INDEX
提示强制使用insert_time
索引(需确保其确实更优):EXPLAIN SELECT * FROM tb_oc_order FORCE INDEX (insert_time_index_name) WHERE transaction_id = '202502260333525000251000008' AND insert_time >= '2024-02-26 09:23:15';
-
检查数据分布
执行以下查询,确认满足条件的数据比例:-- 满足 insert_time 条件的数据占比 SELECT COUNT(*) / (SELECT COUNT(*) FROM tb_oc_order) AS ratio FROM tb_oc_order WHERE insert_time >= '2024-02-26 09:23:15'; -- 满足 transaction_id 条件的数据行数 SELECT COUNT(*) FROM tb_oc_order WHERE transaction_id = '202502260333525000251000008';
- 如果
transaction_id
匹配行数极少(如 1 行),但insert_time
范围覆盖大部分表,优化器可能优先全表扫描。
- 如果
优化后的执行计划
创建复合索引后,执行计划应类似以下结果(使用索引范围扫描):
+----+-------------+-------------+------+---------------------+---------------------+---------+-------+------+-----------------------+
| id | select_type | table | type | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------+---------------------+---------------------+---------+-------+------+-----------------------+
| 1 | SIMPLE | tb_oc_order | ref | idx_trans_insert | 772 (transaction_id)| const | 1 | Using index condition |
+----+-------------+-------------+------+---------------------+---------------------+---------+-------+------+-----------------------+