1. 索引基础与核心价值
在数据库性能优化领域,索引就像图书馆的图书目录系统。我处理过的一个电商平台案例中,没有索引的商品表查询需要3.2秒,添加合适索引后降至48毫秒。索引本质上是一种特殊的数据结构,通过预先排序的键值对加速数据检索。
B+树是MySQL最常用的索引结构,其优势在于:
- 三层结构可支撑千万级数据(高度通常为2-4层)
- 叶子节点形成链表支持范围查询
- 非叶子节点只存键值不存数据,单个节点可容纳更多指针
注意:虽然哈希索引时间复杂度是O(1),但InnoDB只有自适应哈希索引,且不支持范围查询,实际生产环境还是以B+树为主
2. 索引类型深度解析
2.1 物理存储分类
- 聚簇索引:InnoDB的主键索引,数据与索引同文件(.ibd)
sql复制-- 文件大小对比示例 SHOW TABLE STATUS LIKE 'orders'; - 二级索引:存储主键值而非数据指针,回表查询是主要性能瓶颈
2.2 逻辑功能分类
- 普通索引:最基本的索引类型
sql复制CREATE INDEX idx_name ON products(product_name); - 唯一索引:包含NULL处理机制
sql复制CREATE UNIQUE INDEX uid_idx ON users(identity_no); - 联合索引:最左前缀原则实战
sql复制-- 有效使用索引 SELECT * FROM logs WHERE date='2023-01-01' AND app='payment'; -- 索引失效 SELECT * FROM logs WHERE app='payment';
3. 索引创建高级策略
3.1 字段选择黄金法则
- 高区分度字段优先:性别字段索引效果差,手机号索引效果好
- 常用WHERE条件必建:通过慢查询日志分析
sql复制-- 查询区分度 SELECT COUNT(DISTINCT status)/COUNT(*) AS selectivity FROM orders;
3.2 覆盖索引优化
避免回表查询的终极方案:
sql复制-- 需要回表
SELECT * FROM users WHERE age > 25;
-- 覆盖索引
SELECT id, age FROM users WHERE age > 25;
3.3 索引合并陷阱
MySQL5.0+支持的优化策略,但效率通常不如联合索引:
sql复制-- 索引合并
EXPLAIN SELECT * FROM employees
WHERE first_name = 'John' OR last_name = 'Doe';
4. 索引使用避坑指南
4.1 索引失效七大场景
- 隐式类型转换
sql复制-- user_id是varchar类型时 SELECT * FROM users WHERE user_id = 10086; - 函数操作字段
sql复制SELECT * FROM orders WHERE DATE(create_time) = '2023-01-01'; - 前导模糊查询
sql复制SELECT * FROM products WHERE name LIKE '%手机';
4.2 执行计划分析
关键指标解读:
sql复制EXPLAIN FORMAT=JSON
SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE vip=1);
- type列:从优到差 system > const > eq_ref > ref > range > index > ALL
- Extra列:Using filesort、Using temporary需要重点关注
5. 索引维护与调优
5.1 索引碎片整理
定期维护脚本示例:
sql复制-- 查看碎片率
SELECT
table_name,
index_name,
ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2) AS size_mb,
stat_description
FROM mysql.innodb_index_stats
WHERE database_name = 'mydb';
-- 重建索引
ALTER TABLE orders ENGINE=InnoDB;
5.2 索引监控方案
实时监控索引使用情况:
sql复制-- 开启性能模式
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE '%events_statements%';
-- 查询未使用索引
SELECT * FROM sys.schema_unused_indexes;
5.3 索引设计checklist
我的团队使用的设计规范:
- 单表索引不超过5个
- 联合索引字段不超过3个
- 字符串索引长度使用前缀索引
sql复制CREATE INDEX idx_email ON users(email(10)); - 更新频繁的字段谨慎建索引
在最近的数据仓库项目中,通过重构索引策略将报表生成时间从47分钟降至9分钟。关键是把10个单列索引合并为3个精心设计的联合索引,并增加了2个覆盖索引。记住,索引不是越多越好,就像药不是吃得越多越健康