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

数据库索引失效的原因+示例

数据库索引失效的核心原因

查询条件无法触发索引的有序性或选择性,导致数据库放弃索引转而执行全表扫描。

高频失效场景实例

一、索引列参与运算:破坏索引值的有序性

索引本质是按 “索引列原始值” 排序的结构,若查询中对索引列进行函数、算术等运算,数据库无法直接匹配索引值,只能全表计算后筛选。

  • 表结构user(id, age, name)age 列建立普通索引 idx_age
  • 失效 SQL查询年龄大于 30 的用户,对 age 做加法运算。
    SELECT * FROM user WHERE age + 1 > 31; 
    

    数据库需先计算每一行的 age + 1,再判断是否大于 31,无法使用 idx_age,触发全表扫描。
  • 生效 SQL将运算移到条件值侧,保留索引列原始值。
    SELECT * FROM user WHERE age > 31 - 1; -- 等价于 age > 30
    

二、索引列使用函数:索引值无法匹配

与运算类似,函数会改变索引列的原始值,导致索引的有序结构失效,数据库必须全表执行函数后筛选。

  • 表结构order(id, create_time, amount)create_time 建立索引 idx_create_time
  • 失效 SQL查询 2024 年 1 月的订单,对 create_time 使用 DATE_FORMAT 函数。
    SELECT * FROM order WHERE DATE_FORMAT(create_time, '%Y-%m') = '2024-01';
    

    数据库需对所有行的 create_time 执行函数转换,无法利用索引的时间排序,导致全表扫描。
  • 生效 SQL用范围查询匹配索引列原始值(需确保 create_time 格式正确)。
    SELECT * FROM order WHERE create_time BETWEEN '2024-01-01 00:00:00' AND '2024-01-31 23:59:59';
    

三、使用 “不等于” 或否定判断:索引选择性失效

索引的优势是 “快速定位符合条件的行”,而 !=<>NOT INIS NOT NULL 等否定条件,会导致符合条件的行分散在全表,索引无法高效筛选,通常触发全表扫描。

  • 表结构product(id, status, price)status 建立索引 idx_statusstatus 取值:0 - 下架,1 - 上架)。
  • 失效 SQL查询非上架状态的商品(否定判断)。
    SELECT * FROM product WHERE status != 1; -- 等价于 status = 0
    
    即使结果集很小,数据库也可能放弃索引(不同引擎优化策略有差异,但若 status 取值更多,失效概率极高)。
  • 生效 SQL用正向条件明确匹配索引值。
    SELECT * FROM product WHERE status = 0;
    

四、字符串不加引号:触发隐式类型转换

若索引列是字符串类型(如 varchar),查询时条件值不加引号,数据库会将索引列隐式转换为数值类型(如 varchar -> int),相当于对索引列执行 “隐形函数”,导致索引失效。

  • 表结构user(id, phone, address)phone 建立索引 idx_phonephone 类型:varchar(20))。
  • 失效 SQL查询手机号为 13800138000 的用户,条件值不加引号。
    SELECT * FROM user WHERE phone = 13800138000; -- 数值类型 vs 字符串索引列
    
    数据库会执行 CAST(phone AS UNSIGNED) 转换,破坏索引结构,触发全表扫描。
  • 生效 SQL条件值加引号,确保类型匹配。
    SELECT * FROM user WHERE phone = '13800138000';
    

五、模糊查询 “% 开头”:无法利用前缀索引

字符串索引默认是 “前缀索引”(按字符串前 N 个字符排序),若模糊查询用 % 开头(如 %abc),索引无法定位到起始字符,只能全表匹配。

  • 表结构article(id, title, content)title 建立索引 idx_titletitle 类型:varchar(100))。
  • 失效 SQL查询标题包含 “数据库” 的文章,% 开头。
    SELECT * FROM article WHERE title LIKE '%数据库%';
    
    索引按 title 前缀排序,无法确定 “数据库” 在标题中的位置,只能全表扫描。
  • 生效 SQL% 仅在末尾(前缀匹配),利用索引有序性。
    SELECT * FROM article WHERE title LIKE '数据库%'; -- 匹配“数据库入门”“数据库优化”等
    

六、联合索引不满足 “最左前缀原则”:索引断裂

联合索引(如 idx_a_b_c)的排序逻辑是 “先按 A 排,A 相同再按 B 排,B 相同再按 C 排”,查询时必须从最左列 A 开始匹配,否则索引无法生效(部分场景可能触发 “索引覆盖”,但非完整索引利用)。

  • 表结构order(id, user_id, product_id, create_time),建立联合索引 idx_user_product(user_id, product_id)
  • 失效 SQL跳过最左列 user_id,直接查询 product_id
    SELECT * FROM order WHERE product_id = 1001;
    
    联合索引 idx_user_product 以 user_id 为排序基础,无 user_id 条件时,无法定位 product_id 的位置,索引失效。
  • 生效 SQL包含最左列 user_id,符合最左前缀原则。
    SELECT * FROM order WHERE user_id = 501 AND product_id = 1001;
    

总结

索引失效的本质是查询条件破坏了索引的 “有序性” 或 “选择性”

核心规避原则有 3 点:

  1. 索引列不做运算、不套函数,保持原始值匹配;
  2. 条件类型与索引列一致,避免隐式转换;
  3. 联合索引必须从最左列开始匹配,模糊查询避免 % 开头。

http://www.dtcms.com/a/361503.html

相关文章:

  • 视觉引导机械手双夹爪抓取:偏心旋转补偿与逆运动学求解
  • 卷积神经网络训练全攻略:从理论到实战
  • 【K8s】整体认识K8s之Configmap、Secret/ResourceQuota资源配额/访问控制
  • HTTP/2 多路复用
  • [C语言] 结构体 内存对齐规则 内存大小计算
  • 基于springboot生鲜交易系统源码和论文
  • 一文读懂k8s的pv与pvc原理
  • 威科夫与高频因子
  • 2.充分条件与必要条件
  • Android Framework打电话禁止播放运营商视频彩铃
  • Coze源码分析-工作空间-资源库-前端源码
  • Frida Hook 算法
  • 音频数据集采样率选择建议
  • 从网络层接入控制过渡到应用层身份认证的过程
  • 电源相关零碎知识总结
  • 如何把指定阿里云文件夹下的所有文件移动到另一个文件夹下,移动文件时把文件名称(不包括文件后缀)进行md5编码
  • @Autowired注入底层原理
  • 吴恩达机器学习补充:决策树和随机森林
  • AUTOSAR AP R24-11 Log and Trace 文档总结
  • 贪心算法解决钱币找零问题(二)
  • CentOS10安装RabbitMQ
  • [特殊字符]【C语言】超全C语言字符串处理函数指南:从原理到实战
  • ARM的编程模型
  • TikTok Shop 物流拖后腿?海外仓系统破解物流困局
  • nginx是什么?
  • MQ使用场景分析
  • OpenHarmony 分布式感知中枢深度拆解:MSDP 框架从 0 到 1 的实战指南
  • 2025年- H104-Lc212--455.分发饼干(贪心)--Java版
  • 电动自行车淋水安全测试的关键利器:整车淋水性能测试装置的技术分析
  • 零基础深度学习技术学习指南:从入门到实践的完整路径