什么?你的 SQL 索引可能白加了!?

最近发现公司的订单查询越来越慢,明明给 order_date 加了索引,可查询速度还是像蜗牛爬。盯着屏幕上的 SQL 语句和索引列表,百思不得其解------"索引明明存在,为什么数据库就是不用?" 一线的同志们,你们遇到过没?那有可能索引还真的是加了个寂寞!就像那首歌唱的:"哦!寂寞的夜里,一个人难受,伤心眼泪往下流!"

那么我们一起分析分析呗,别让伤心继续下去!


一、索引失效的经典名场面(附代码验证)

场景 1:最左匹配原则

错误操作:t_user 表建了联合索引 idx_name_age,但查询时跳过了 nick_name

sql 复制代码
-- 创建联合索引
CREATE INDEX idx_name_age ON t_user(nick_name, age);

-- 致命错误:跳过 name 直接查 age(索引失效!)
SELECT * FROM t_user WHERE age = 30; -- 全表扫描

执行计划真相(MySQL 8.0):

原理:联合索引就像电话簿的"姓+名",只查"名"时索引无法定位数据位置。


场景 2:隐式类型转换

错误操作: order_id 是字符串类型(VARCHAR),却用数字查询。

sql 复制代码
-- order_id 是 VARCHAR(20)

CREATE INDEX idx_order_id ON t_order(order_id);

<!--  致命错误:虽然查出来,(字符串当数字用(索引失效!) -->
SELECT * FROM t_order WHERE order_id = 666;

执行计划真相:

sql 复制代码
<!-- 但是我们得看内部详细 -->

EXPLAIN SELECT * FROM t_order WHERE order_id = 666;

-- 输出:type=ALL, key=NULL (全表扫描)

原理 :数据库偷偷把 order_id 转成数字再比较,相当于对索引列做了函数计算。


场景 3:索引列上做计算

错误操作: 在索引列 price 上做数学计算。

sql 复制代码
CREATE INDEX idx_price ON t_user(balance);

-- 致命错误:索引列参与计算(索引失效!)
SELECT * FROM  t_user WHERE balance * 0.9 > 100; 


EXPLAIN  SELECT * FROM  t_user WHERE balance * 0.9 > 100;

正确写法:

sql 复制代码
SELECT * FROM t_user WHERE balance > 100 / 0.9; -- 计算移到右侧

EXPLAIN SELECT * FROM t_user WHERE balance > 100 / 0.9;

二、索引加了为何不用?

数据库选择索引不是看"有没有",而是看"值不值":

  1. 成本太高: 当需要回表查询大量数据时,直接全表扫描可能更快
  2. 数据倾斜: 如对"性别"字段建索引,因值重复度高(男/女),索引效率低下
  3. 统计信息过时: 数据库误判数据分布,以为全表扫描更优

三、这样加索引才有效!

策略 1:联合索引的黄金排列法则

口诀:高频查询字段在前,高区分度字段优先

sql 复制代码
-- 正确姿势:name 区分度高且常被查询
CREATE INDEX idx_name_age_state ON t_user(nick_name, age, state);

策略 2:拒绝隐式转换,类型严格一致

sql 复制代码
-- 正确姿势:保持类型一致
SELECT * FROM t_order WHERE order_id = '666'; -- 用字符串查字符串

策略 3:利用覆盖索引减少回表

sql 复制代码
-- 只查索引包含的列,避免回表
SELECT nick_name, age FROM t_user WHERE age > 25; -- 若索引是 (age,nick_name) 则高效

四、实战检测:你的索引真的生效了吗?

EXPLAIN 看关键指标:

sql 复制代码
EXPLAIN SELECT name FROM users WHERE age = 30 AND city='Beijing';

有效索引信号:

  • type = ref/range
  • key = 你的索引名
  • Extra = Using index(覆盖索引)

危险信号:

  • type = ALL
  • key = NULL
  • Extra = Using filesort/Using temporary

五、索引使用的三大铁律

  1. 最左匹配是底线: 联合索引查询必须从左连续使用
  2. 类型一致保平安: 避免隐式转换让索引失效
  3. 计算不在索引列: 将计算、函数移到查询条件右侧

🚨 提醒:写到最后,提醒各位喜欢使用索引的同志们,定期用 EXPLAIN 检查执行计划,看看你的索引是否白加了。不要到最后时伤心的眼泪才往下流,到时盆儿都接不住了!!!


相关推荐
神奇的程序员1 小时前
从已损坏的备份中拯救数据
运维·后端·前端工程化
oden2 小时前
AI服务商切换太麻烦?一个AI Gateway搞定监控、缓存和故障转移(成本降40%)
后端·openai·api
玄斎3 小时前
MySQL 单表操作通关指南:建库 / 建表 / 插入 / 增删改查
运维·服务器·数据库·学习·程序人生·mysql·oracle
李慕婉学姐3 小时前
【开题答辩过程】以《基于Android的出租车运行监测系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·后端·vue
m0_740043733 小时前
SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j
java·spring boot·后端·log4j
编程小Y4 小时前
MySQL 与 MCP 集成全解析(核心原理 + 实战步骤 + 应用场景)
数据库·mysql·adb
招风的黑耳4 小时前
我用SpringBoot撸了一个智慧水务监控平台
java·spring boot·后端
Miss_Chenzr4 小时前
Springboot优卖电商系统s7zmj(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
期待のcode4 小时前
Springboot核心构建插件
java·spring boot·后端
2501_921649494 小时前
如何获取美股实时行情:Python 量化交易指南
开发语言·后端·python·websocket·金融