导读:本期聚焦于小伙伴创作的《MySQL添加索引有哪几种方式?各自适用什么场景?》,敬请观看详情。一张千万级订单表查询越来越慢,加索引是最直接的优化手段,但用错方式可能锁表数小时。MySQL里建索引并不只有CREATE INDEX一种办法,ALTER TABLE、CREATE TABLE时顺带定义、以及在线无锁的INSTANT或INPLACE算法差异很大。新手常以为加索引必然阻塞写入,其实从5.6开始InnoDB已支持在线DDL,不过仍要区分是否允许并发DML。理清这些创建路径和底层实现,才能在大表运维时选对命令,避免业务停摆。

在MySQL数据库的运维和开发过程中,为表添加索引是提升查询性能最常见的操作。不同的添加方式在语法、锁表行为、执行效率以及对线上业务的影响上都有明显区别。理解这些方式的差异,能帮助我们针对小表、大表、以及高并发场景选择最合适的建索引方案。

MySQL添加索引有哪几种方式?各自适用什么场景?

一、使用CREATE INDEX语句添加索引

CREATE INDEX是最直观、语义最清晰的添加索引方式,它属于标准SQL语法,在MySQL中会被映射为ALTER TABLE操作。通过这种方式可以创建普通索引、唯一索引、全文索引等,但不能用来创建主键索引。

下面示例为user表的email字段创建唯一索引,避免重复注册:

-- 创建普通索引
CREATE INDEX idx_name ON user(name);

-- 创建唯一索引
CREATE UNIQUE INDEX uk_email ON user(email);

-- 创建组合索引
CREATE INDEX idx_age_city ON user(age, city);

这种写法在MySQL 5.6之前的大表上执行时,默认会阻塞表的写入和读取,直到索引构建完成。从MySQL 5.6开始,InnoDB引擎支持在线DDL,CREATE INDEX默认采用INPLACE算法,允许在索引创建期间并发执行DML语句,大大降低了加索引对业务的影响。

需要注意的是,虽然在线创建索引允许并发DML,但在索引构建的某些阶段仍会获取元数据锁(MDL),如果此时有长事务未提交,可能造成锁等待。因此执行前应当检查是否有慢查询或长事务占用表。

二、使用ALTER TABLE语句添加索引

ALTER TABLE是MySQL内部真正执行索引变更的命令,CREATE INDEX本质上也是转换成ALTER TABLE ... ADD INDEX。使用ALTER TABLE可以添加包括主键在内的各类索引,语法更加灵活。

以下示例展示通过ALTER TABLE添加主键和二级索引:

-- 添加主键索引
ALTER TABLE user ADD PRIMARY KEY(id);

-- 添加普通索引
ALTER TABLE user ADD INDEX idx_phone(phone);

-- 添加全文索引
ALTER TABLE article ADD FULLTEXT INDEX ft_title(title);

ALTER TABLE在添加索引时可以显式指定算法和锁策略,例如使用ALGORITHM=INPLACE和LOCK=NONE来强制在线无锁构建。对于不支持INPLACE的索引类型(如某些全文索引),则需要使用ALGORITHM=COPY,此时会复制整张表,性能开销很大。

在实际生产中,如果要对大表加索引,推荐明确写出ALGORITHM和LOCK参数,让执行计划更可控。若数据库版本较旧不支持在线DDL,则应安排在业务低峰期,并考虑使用pt-online-schema-change等第三方工具来规避锁表问题。

三、建表时直接定义索引

在CREATE TABLE语句中直接定义索引,是开发阶段最常用的方式。此时表还没有数据或数据量极小,索引会随着表创建一并建立,不存在后期大表加索引的性能隐患。

示例在建表时定义主键、唯一索引和组合索引:

CREATE TABLE order_info (
    id BIGINT NOT NULL AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    status TINYINT NOT NULL,
    created_at DATETIME NOT NULL,
    PRIMARY KEY(id),
    UNIQUE KEY uk_order_no(order_no),
    KEY idx_user_status(user_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

这种方式适合项目初期或新功能上线时规划好查询模式,提前建立索引。由于建表时数据为空,索引构建成本极低。但如果在设计阶段遗漏了高频查询字段的索引,后续仍要通过前面两种方式补建。

需要提醒的是,在CREATE TABLE中定义外键时,MySQL会自动为该列创建索引,这是隐式行为,开发者应了解这一机制,避免重复创建造成资源浪费。

四、不同添加方式的对比与选型

为了更清晰地看出差异,我们从锁表情况、适用阶段和复杂度三个维度对比上述方式:

添加方式是否支持在线DDL适用场景能否建主键
CREATE INDEX默认INPLACE(5.6+)已有表补索引
ALTER TABLE ADD INDEX可显式控制已有表补索引、改结构
CREATE TABLE定义不涉及新建表初期

从运维角度看,如果表数据量在百万以内,任何方式差异不大;当表数据超过千万,必须优先使用支持INPLACE的ALTER TABLE并指定LOCK=NONE,或者采用gh-ost等工具。建表时定义索引则是成本最低的方案,应当在设计评审时充分考虑。

另外,添加索引后应通过EXPLAIN验证查询是否真正走了索引,避免由于字段类型不匹配或函数包裹导致索引失效,那样即使添加了索引也无性能收益。

五、添加索引的注意事项

首先,索引并非越多越好。每个索引都会占用存储空间,并在写入时增加维护成本。对于写多读少的表,应当精简索引数量,只保留核心查询所需。

其次,大表在线加索引虽然支持并发DML,但仍会消耗大量IO和CPU,建议在资源空闲时执行,并监控主从延迟,避免从库重放缓慢导致读写分离失效。以下命令可查看当前DDL进度(MySQL 5.7+):

-- 查看长任务进度
SELECT * FROM performance_schema.events_stages_current
WHERE EVENT_NAME LIKE '%alter%';

最后,添加索引前应在测试环境用接近生产的数据量验证,确认语法和性能符合预期。如果是云数据库,也可利用其提供的在线变结构功能,进一步降低操作风险。

MySQL添加索引索引创建方式修改时间:2026-08-04 23:36:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。