当前位置: 首页 > news >正文

mysql有索引但是查询没有使用索引是什么问题

关键原因分析

  1. 索引选择性问题

    • 如果 order_id 没有索引,即使 insert_time 有索引,优化器可能认为先通过 order_id 过滤数据更高效。但由于 order_id 无索引,只能全表扫描后过滤。
    • 即使 insert_time 有索引,如果满足 insert_time >= '2024-02-26' 的数据量很大(如超过表总行数的 20%),优化器会认为全表扫描比回表更高效
  2. 缺乏复合索引
    单列索引 insert_time 仅能加速时间范围过滤,但无法同时优化 order_id 的等值查询。若 order_id 的过滤性(选择性)高,优化器更倾向于使用复合索引 (order_id, insert_time)

  3. 统计信息不准确
    表的统计信息(如索引基数)过期,导致优化器误判索引效果。可通过 ANALYZE TABLE tb_oc_order; 更新统计信息。

  4. 隐式类型转换或函数调用
    如果 transaction_id 的字符集或排序规则与查询值不匹配,可能导致隐式转换,从而无法使用索引(需检查表结构)。


解决方案

  1. transaction_id 添加索引
    如果 transaction_id 选择性高(如唯一或接近唯一),优先为其单独创建索引:

    ALTER TABLE tb_oc_order ADD INDEX idx_transaction_id (transaction_id);
    
  2. 创建复合索引
    联合索引 (transaction_id, insert_time) 可以同时优化两个条件:

    ALTER TABLE tb_oc_order ADD INDEX idx_trans_insert (transaction_id, insert_time);
    
    • 优势:先通过 transaction_id 快速定位少量行,再按 insert_time 过滤,效率更高。
  3. 强制使用索引(谨慎使用)
    通过 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';
    
  4. 检查数据分布
    执行以下查询,确认满足条件的数据比例:

    -- 满足 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 |
+----+-------------+-------------+------+---------------------+---------------------+---------+-------+------+-----------------------+

相关文章:

  • [uboot][stm32]配置LTDC屏幕
  • AI如何改变传统工厂的生产模式?
  • Nginx 平滑升级/回滚
  • 免费的 S3 客户端工具:s3cmd
  • 特斯拉 FSD 算法深度剖析:软件层面全解读
  • 深入理解Java多线程编程:从基础到高级应用
  • 【机器人系列之硬件和软件架构设计】
  • OpenHarmony应用间跳转
  • Lua的table(表)
  • JSON Schema 入门指南:如何定义和验证 JSON 数据结构
  • QT和有道词典有冲突,导致内存溢出,闪退。
  • neo4j 和 langchain_community.graphs.Neo4jGraph 对比
  • 前缀和专题练习 ——基于罗勇军老师的《蓝桥杯算法入门C/C++》
  • 机试刷题_NC17 最长回文子串【python】
  • PostgreSQL:模拟插入数据和查询(带时间)
  • 三轴加速度推算姿态角的方法,理论分析和MATLAB例程
  • Leetcode3162:优质数对的总数 I
  • Spring Boot @Async 注解深度指南
  • 湘潭大学计算机复试详细攻略(调剂)
  • Ubuntu 下 nginx-1.24.0 源码分析 - NGX_CYCLE_POOL_SIZE 宏
  • 蔡达峰:推动食品安全法全面有效实施,为维护人民群众身体健康提供有力法治保障
  • 85后清华博士黄佐财任湖北咸宁市咸安区委副书记、代区长
  • 金融监管总局:力争实现全国普惠型小微企业贷款增速不低于各项贷款增速
  • 巴基斯坦所有主要城市宣布进入紧急状态,学校和教育机构停课
  • 这个接班巴菲特的男人,说不出一个打动人心的故事
  • 短剧剧组在贵州拍戏突遇极端天气,演员背部、手臂被冰雹砸伤