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

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


http://www.kler.cn/a/562712.html

相关文章:

  • mac修改docker的daemon.json 镜像文件
  • DeepSeek:面向效率与垂直领域的下一代大语言模型技术解析
  • Deepseek底层技术解析:构建下一代对话式AI的核心架构
  • 【Linux C | 时间】localtime 的介绍、死机、死锁问题以及 localtime_r 函数的时区问题
  • C语言实现通讯录项目
  • 基于Zigbee的三车协作智能小车项目改进方案
  • python学习四
  • 计算机视觉:经典数据格式(VOC、YOLO、COCO)解析与转换(附代码)
  • idea创建第一个springboot程序
  • 数据开发面试:DQL,
  • 深入解析 Linux /etc/skel 目录的作用与使用方法
  • C# 打印Word文档 – 4种打印方法
  • PDF转HTML 超级好用 免费在线转换PDF 完美转换格式
  • 微信小程序记录用户在图书详情页面停留时间--即阅读时间,如果超过两小时,则每小时提醒用户一次
  • 【安卓逆向】逆向APP界面UI修改再安装
  • labview关于计时器的使用
  • Mac 上安装多版本的 JDK 且实现 自由切换
  • TCP 协议相关的参数(KeepAliveTime、KeepAliveInterval、TcpMaxDataRetransmissions)
  • DeepSeek开源周第二日-DeepEP
  • 实现分布式限流开源项目