选择合适的 MySQL 索引,核心是让查询尽可能快地定位到数据,同时避免过度索引带来的写入开销和存储浪费。关键不在于“加得多”,而在于“加得准”——匹配查询模式、覆盖常用条件、兼顾更新频率。
优先为 WHERE、JOIN、ORDER BY 和 GROUP BY 中的字段建索引
MySQL 只有在能利用索引加速扫描时才会真正用上索引。常见有效场景包括:
WHERE 条件中的等值查询(=、IN)或范围查询(>、:例如WHERE status = 'active' AND created_at > '2024-01-01',适合在
(status, created_at)上建联合索引; 多表 JOIN 的关联字段:如
ON orders.user_id = users.id,两边字段都应有索引,尤其被驱动表(通常是右表)的关联列必须有索引; ORDER BY 或 GROUP BY 的字段:若查询含
ORDER BY create_time DESC且无对应索引,MySQL 可能触发 filesort,影响性能; 注意:LIKE 前缀通配(如
LIKE '%abc')无法使用索引;只有
LIKE 'abc%'这类左匹配才可走索引。
合理设计联合索引,遵循最左前缀原则
联合索引
(a, b, c)实际上同时支持以下查询条件:
a = ?
a = ? AND b = ?
a = ? AND b = ? AND c = ?
a = ? AND b IN (?, ?) AND c = ?(部分优化器支持)
但不支持
b = ?或
c = ?单独查询,也不支持跳过中间列(如
a = ? AND c = ?)。因此建联合索引时,把区分度高、过滤性强的字段放前面,常用于排序/分组的字段靠后放置。
谨慎对待索引列的数据类型与长度
索引效率受字段类型直接影响:
优先使用整型(如INT、
BIGINT)而非字符串做主键或关联字段,比较快、占用小; 对长文本字段(如
VARCHAR(500))建索引时,考虑前缀索引:
INDEX idx_title (title(100)),平衡区分度与空间; 避免在频繁更新的字段(如状态字段只有 0/1)上单独建索引——区分度低,反而增加维护成本; 日期时间字段(
DATETIME)可建索引,但要注意是否真的参与高效过滤(比如查“最近7天”比查“某一天”更易命中索引范围扫描)。
定期评估与清理无效/冗余索引
上线后索引不是一劳永逸。可通过以下方式识别问题索引:
查information_schema.statistics或使用
SHOW INDEX FROM table_name查看现有索引; 结合慢查询日志 +
EXPLAIN分析实际执行计划,确认索引是否被命中、是否发生索引下推(ICP)、是否回表过多; 使用
sys.schema_unused_indexes(MySQL 5.7+)快速发现长期未被使用的索引; 警惕冗余索引:如已有
(a, b),再建
(a)就是冗余;已有
(a, b, c),再建
(a, b)通常也不必要(除非业务明确只需要前两列)。
