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

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

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

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

高频失效场景实例

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

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

  • 表结构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.xdnf.cn/news/19525.html

相关文章:

  • (线上问题排查)3.线上API接口响应慢?一套高效排查与定位问题的心法
  • OpenCV-Python Tutorial : A Candy from Official Main Page(五)
  • Roo Code自定义Mode(模式)
  • 基于单片机智能家居环境监测报警系统Proteus仿真(含全部资料)
  • Cesium 加载桥梁3DTiles数据时,出现部分区域发暗、部分正常的现象
  • openEuler2403编译安装Nginx
  • 【期末复习】--软件工程
  • 苍穹外卖项目实战(日记十三)-记录实战教程及问题的解决方法-(day3-5) 修改菜品功能实现
  • C++ Bellman-Ford算法
  • 「数据获取」《中国住户调查年鉴》(2000-2024)(获取方式看绑定的资源)
  • # [特殊字符] 构建现代化黄金价格实时仪表盘:技术解析与实践
  • AI产品经理面试宝典第81天:RAG系统架构演进与面试核心要点解析
  • C++11新特性解析与应用
  • GPU 通用手册:裸机、Docker、K8s 环境实战宝典
  • Jetson AGX Orin平台R36.3.0版本1080P25fps MIPI相机图像采集异常调试记录
  • 在idea当中git的基础使用
  • 【公告】更新预告
  • 1.4 汽车的制动性
  • 面向对象六大设计原则(2.0详细版)
  • 永磁同步电机无速度算法--高频脉振方波注入法(测量轴系转子位置误差信号解耦处理)
  • Ansible 变量全解析与实践
  • MySQL DBA请注意 不要被Sleep会话蒙蔽了双眼
  • 【算法】124.二叉树中的最大路径和--通俗讲解
  • DeepSeek-V3.1 模型 API 新特性拆解:逆向 + 火山双渠道适配与推理模式智能切换指南
  • 保健品跨境电商:如何筑牢产品质量与安全防线?
  • 【推荐】Maye 更轻更简洁的快速启动工具【优化桌面】
  • AutoSar RTE介绍
  • FOC+MCU:重新定义吸尘器电机控制——高效、静音、智能的终极解决方案
  • LeetCode199. 二叉树的右视图 - 解题思路与实现
  • Linux Tun/Tap 多队列技术