MySQL索引是提升数据库查询效率的核心手段,但若设计和使用不规范,不仅无法发挥索引的作用,还会带来额外的存储和性能开销。整理一套通用的MySQL索引规范,能帮助开发者规避常见问题,让索引设计更合理。

索引设计基础规范
索引类型选择规范
首先需要根据业务场景选择合适的索引类型,不同索引类型的适用场景差异较大:
- 普通索引:适用于大部分常规查询场景,仅用于加速查询,无唯一性约束
- 唯一索引:适用于需要保证字段值唯一性的场景,比如用户手机号、邮箱字段,同时具备查询加速能力
- 主键索引:每张表必须有且仅有一个主键索引,建议优先使用自增整数类型作为主键,避免使用UUID等无序字符串
- 联合索引:适用于多字段组合查询的场景,需要遵循最左前缀原则设计字段顺序
- 全文索引:仅适用于文本字段的大范围模糊查询场景,比如文章内容搜索,普通like模糊查询不建议使用全文索引
索引字段选择规范
不是所有字段都适合创建索引,需要遵循以下选择原则:
- 优先选择查询条件中频繁出现的字段,比如where子句、join连接条件、order by排序字段、group by分组字段
- 尽量选择区分度高的字段,区分度计算公式:count(distinct 字段)/count(*),值越接近1区分度越高,比如用户ID的区分度远高于性别字段
- 避免使用频繁更新的字段作为索引,每次更新字段都需要同步更新索引结构,会增加写入开销
- 尽量避免选择过长的字段作为索引,比如超长文本字段,若必须使用可以截取字段的前缀创建前缀索引
索引命名与使用规范
索引命名规范
统一的索引命名规则能提升数据库的可维护性,建议遵循以下规则:
- 普通索引命名格式:idx_字段名,比如用户表的手机号索引可以命名为idx_phone
- 唯一索引命名格式:uk_字段名,比如用户表的邮箱唯一索引可以命名为uk_email
- 联合索引命名格式:idx_字段1_字段2_字段n,按照联合索引的字段顺序命名,比如idx_user_id_create_time
- 主键索引统一命名为PRIMARY,MySQL默认主键索引名称,不需要额外自定义
- 全文索引命名格式:ft_字段名,比如文章表的content字段全文索引可以命名为ft_content
联合索引使用规范
联合索引是最容易出现使用问题的索引类型,需要遵守以下使用规则:
- 严格遵循最左前缀原则,联合索引idx_a_b_c只能生效于查询条件包含a、a+b、a+b+c的场景,无法生效于单独查询b、c或者b+c的场景
- 联合索引的字段顺序建议把区分度最高的字段放在最左侧,其次是查询频率最高的字段
- 范围查询字段尽量放在联合索引的最后,比如查询条件为a=1 and b>10 and c=20,联合索引建议设计为idx_a_c_b,因为b是范围查询,放在最后不会影响c的索引生效
索引维护与避坑规范
冗余索引规避规范
冗余索引会浪费存储空间,还会增加写入时的索引更新开销,需要定期排查:
- 已经存在联合索引idx_a_b的情况下,不需要再单独创建idx_a索引,因为联合索引已经可以覆盖a字段的查询场景
- 主键索引已经具备唯一性,不需要再给主键字段创建唯一索引
- 定期通过数据库命令排查冗余索引,比如执行
SELECT * FROM sys.schema_redundant_indexes;查看冗余索引列表
常见使用避坑规范
即使索引设计合理,使用不当也会导致索引失效,需要规避以下场景:
- 查询条件中对索引字段使用函数或者运算,比如
where year(create_time)=2024,会导致create_time的索引失效 - 查询条件中使用like以通配符开头,比如
where name like '%张三',会导致name的索引失效,where name like '张三%'可以正常使用索引 - 查询条件中索引字段发生隐式类型转换,比如索引字段是字符串类型,查询时传入数字,
where phone = 13800138000,会导致phone索引失效 - 使用
select *查询时,若联合索引无法覆盖所有查询字段,会触发回表操作,建议按需查询字段,尽量使用覆盖索引
索引规范落地示例
以下是一个用户表的设计示例,符合上述索引规范:
-- 创建用户表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID,自增主键', `username` varchar(50) NOT NULL COMMENT '用户名', `phone` varchar(20) NOT NULL COMMENT '手机号', `email` varchar(100) DEFAULT NULL COMMENT '邮箱', `gender` tinyint(1) DEFAULT NULL COMMENT '性别 0未知 1男 2女', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_phone` (`phone`), UNIQUE KEY `uk_email` (`email`), KEY `idx_username` (`username`), KEY `idx_create_time` (`create_time`), KEY `idx_gender_create_time` (`gender`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
上述表结构中,主键使用自增id,手机号、邮箱使用唯一索引保证唯一性,用户名、创建时间使用普通索引加速查询,性别和创建时间创建联合索引覆盖按性别筛选并按时间排序的查询场景,没有冗余索引,符合所有设计规范。
索引规范不是一成不变的,需要结合业务的实际查询场景灵活调整,定期分析慢查询日志,针对性优化索引,才能让数据库性能保持在最优状态。