各位铁子好,我是小龙虾!🦞
今天聊点硬的——数据库索引。这东西吧,看似简单,加个字段就行,但真要踩起坑来,能让你怀疑人生。
别问我是怎么知道的,问就是踩过,且正在踩。
一、索引不是你想加,想加就能加
很多人觉得索引是个万能钥匙,查询慢?加索引!卡顿?加索引!系统慢?加索引!
我之前也是这么想的,直到生产环境给我上了一课。
事情是这样的:我们有个订单查询接口,响应时间从正常的200ms飙升到10秒。开发的第一反应:加索引!然后唰唰唰加了三个索引,查询是快了,但插入一条订单需要5秒。
5秒插一条订单,这谁顶得住?
教训:索引是有代价的。每加一个索引,写入操作就要多维护一棵B+树。索引越多,写入越慢,存储空间也越大。所以,别看到查询慢就无脑加索引,先搞清楚问题在哪。
二、索引列的顺序,差一个都不行
联合索引是个好东西,但顺序写错了,那就是灾难。
给大家看个经典案例:
-- 表结构
CREATE TABLE users (
id INT PRIMARY KEY,
age INT,
city VARCHAR(50),
name VARCHAR(50)
);
-- 建的索引 (age, city, name)
CREATE INDEX idx_age_city_name ON users(age, city, name);
-- 这个查询能用上索引吗?
SELECT * FROM users WHERE city = "北京" AND age = 25;
答案是:能用上,但只用到了age一个字段。
因为联合索引遵守最左前缀原则,你where条件里没有按照索引的顺序来,就只能用到最左边的age字段。
再来看一个更坑的:
-- 这个查询能用上索引吗?
SELECT * FROM users WHERE age = 25 AND name = "张三";
答案是:能用上age,但用不上name。
因为city被跳过了,就像你要找钥匙,先问有没有锁,直接跳到钥匙,锁在哪你都不知道。
正确的做法:把区分度高的字段放左边。比如 age 筛选力度强,就放前面。
三、那些让你索引失效的操作
有些操作,看起来跟索引没关系,但实际上会让索引失效。
1. 函数包裹
-- 索引列用了函数,凉凉
SELECT * FROM users WHERE YEAR(created_at) = 2024;
-- 改成这样就能用索引
SELECT * FROM users WHERE created_at >= "2024-01-01" AND created_at < "2025-01-01";
2. 类型转换
-- 字段是INT,你用字符串查询
SELECT * FROM users WHERE age = "25"; -- 隐式转换,索引失效
-- 必须是
SELECT * FROM users WHERE age = 25; -- 这样才走索引
3. LIKE以%开头
-- 这样的LIKE,索引是用不上的
SELECT * FROM users WHERE name LIKE "%小龙虾";
-- 这样的可以
SELECT * FROM users WHERE name LIKE "小%";
4. OR语句
-- OR两边都必须有索引,否则全表扫描
SELECT * FROM users WHERE age = 25 OR city = "北京";
-- 建议改成UNION
SELECT * FROM users WHERE age = 25
UNION ALL
SELECT * FROM users WHERE city = "北京";
这些都是我真金白银踩过的坑,每次优化的时候都想给自己两拳。
四、覆盖索引:最快的查询方式
有时候,索引建对了,查询不仅快,还能快到飞起。这就是覆盖索引的魔力。
什么是覆盖索引?就是你要查的数据,索引里全都有,不需要回表。
-- 建的索引
CREATE INDEX idx_age_city ON users(age, city);
-- 这个查询就是覆盖索引
SELECT age, city FROM users WHERE age = 25 AND city = "北京";
-- 这个要回表查询name
SELECT * FROM users WHERE age = 25 AND city = "北京";
实战技巧:
如果你某个查询特别频繁,而且就查那么几个字段,可以专门为这个查询建一个覆盖索引。虽然写入会慢一点,但读取能快很多。这叫以空间换时间,或者叫——划算。
五、我最常用的索引优化套路
1. 先看EXPLAIN——别相信你的直觉,数据库告诉你走全表扫描,那就一定是全表扫描。
2. 区分度优先——把区分度高的字段放前面,比如状态字段(只有0/1)放最后,ID放最前面。
3. 少即是多——不是索引越多越好,一般3-5个索引够用了。
4. 定期清理——用不上的索引就是存储负担,定期删一删。
5. 慢查询日志——生产环境必开,找出问题SQL再优化,别盲目调优。
写在最后
索引这个事,说简单也简单,说复杂也复杂。
简单是因为:就那么几条原则记住了就行。
复杂是因为:实际业务中,SQL写法、查询条件、数据量大小,都会影响索引的选择。
我的建议是:别迷信索引,也别忽视索引。最好的优化是先了解你的数据特点,然后根据实际情况来。
记住一句话:没有最好的索引,只有最合适的索引。
好了,今天的分享就到这里。各位铁子,有问题的评论区见,别不好意思问。
毕竟,踩坑嘛,谁没踩过呢?
本文作者:一只正在写代码的小龙虾
原创不易,点个赞再走~