一、为什么要优化索引?
在MySQL数据库中,索引是提升查询性能的关键。根据统计,合理的索引设计可以使查询速度提升10-100倍。但索引也是一把双刃剑:使用得当能极大提升性能,使用不当反而会导致写入变慢、存储空间浪费等问题。
二、索引优化核心策略
1. 选择合适的索引类型
-- 创建索引示例
CREATE INDEX idx_user_age ON users(age); -- B-Tree索引(默认)
CREATE FULLTEXT INDEX idx_content ON articles(content); -- 全文索引
ALTER TABLE orders ADD SPATIAL INDEX idx_geo(location); -- 空间索引
优化建议:
-
80%场景使用B-Tree索引
-
文本搜索使用全文索引(FULLTEXT)
-
地理数据使用空间索引(SPATIAL)
2. 避免过度索引
典型误区:每个字段都建索引
-- 冗余索引示例(需要优化)
CREATE INDEX idx_name ON users(name);
CREATE INDEX idx_name_email ON users(name,email); -- 包含name的联合索引已冗余
优化方案:
-
定期使用
SHOW INDEX FROM table_name
检查索引 -
使用
sys.schema_redundant_indexes
视图(MySQL 8.0+)
3. 最左前缀原则实践
-- 联合索引示例
CREATE INDEX idx_composite ON employees(department_id, salary, hire_date);
-- 有效查询:
SELECT * FROM employees
WHERE department_id = 5 AND salary > 10000;
-- 失效查询:
SELECT * FROM employees
WHERE salary > 10000; -- 未使用索引第一列
关键点:
-
联合索引列顺序=查询条件顺序+排序需求
-
区分度高的列放在左侧
4. 索引列选择黄金法则
优选字段:
-
WHERE子句高频字段
-
JOIN连接字段
-
ORDER BY/GROUP BY字段
-
高区分度字段(如user_id)
避坑指南:
-
避免对长文本建索引(可用前缀索引)
-
谨慎对低区分度字段建索引(如性别字段)
-- 前缀索引示例
CREATE INDEX idx_name_prefix ON customers(name(10)); -- 取前10个字符
5. 覆盖索引优化
原理:索引包含查询需要的所有字段
-- 需要回表
SELECT * FROM products WHERE category = '电子产品';
-- 覆盖索引优化
CREATE INDEX idx_cover ON products(category, price, stock);
SELECT category, price FROM products WHERE category = '电子产品';
6. 索引下推(ICP)
MySQL 5.6+新特性:在存储引擎层过滤数据
-- 启用ICP(默认开启)
SET optimizer_switch = 'index_condition_pushdown=on';
7. 排序优化技巧
-- 需要filesort的查询
SELECT * FROM orders ORDER BY create_time DESC LIMIT 100;
-- 优化方案:
ALTER TABLE orders ADD INDEX idx_time_status (create_time, status);
SELECT * FROM orders
WHERE create_time > '2023-01-01'
ORDER BY create_time DESC LIMIT 100;
三、索引使用注意事项
-
更新代价:索引会增加INSERT/UPDATE/DELETE开销
-
存储成本:每个索引约占表大小的10-30%
-
统计信息:定期执行
ANALYZE TABLE table_name
-
索引失效场景:
-
对索引列进行运算:
WHERE YEAR(create_time) = 2023
-
使用前导通配符:
WHERE name LIKE '%张'
-
隐式类型转换:
WHERE phone = 13800138000
(phone是字符串类型)
-
四、性能验证工具
-
EXPLAIN执行计划:
EXPLAIN SELECT * FROM users WHERE age BETWEEN 20 AND 30;
重点关注:
-
type(访问类型):至少达到range级别
-
key(实际使用索引)
-
Extra:Using index(覆盖索引)
-
慢查询日志分析:
# my.cnf配置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
五、总结
通过合理使用索引,我们成功将某电商平台的订单查询响应时间从2.3秒优化到0.15秒。建议开发者在设计阶段就考虑索引策略,遵循"最少索引,最大收益"原则。记住:索引优化是一个持续的过程,需要结合业务变化不断调整。