create index 仅适用于已存在表,需index权限,语法含索引名、表名、字段名,不支持多索引同语句创建,索引名重复会报错,大表建索引有性能影响。

CREATE INDEX 语句的基本写法和执行前提
MySQL 中 CREATE INDEX 只能对**已存在的表**添加索引,不能在建表时用它定义索引(那是 CREATE TABLE 的事)。执行前必须确保你有该表的 INDEX 权限,否则会报错:ERROR 1142 (42000): INDEX command denied to user。
- 语法必须包含索引名、表名和字段名,例如:
CREATE INDEX idx_name ON users(name); - 不支持一次语句创建多个索引;每个
CREATE INDEX只能定义一个索引 - 如果索引名已存在,MySQL 会直接报错:
ERROR 1061 (42000): Duplicate key name 'idx_name',不会静默覆盖 - 对大表执行时会锁表(尤其 MyISAM),InnoDB 虽支持在线 DDL(8.0+ 默认
ALGORITHM=INPLACE),但仍有性能影响,建议避开业务高峰
单列索引、联合索引与函数索引的区别
索引类型直接影响查询能否命中。MySQL 5.7 开始支持函数索引(实际是表达式索引),但需注意语法限制和使用场景。
- 单列索引:
CREATE INDEX idx_email ON users(email);—— 适用于WHERE email = ?或ORDER BY email - 联合索引:
CREATE INDEX idx_status_created ON orders(status, created_at);—— 遵循最左前缀原则,WHERE status = 1 AND created_at > '2023-01-01'可用,但WHERE created_at > '2023-01-01'不可用 - 函数索引(MySQL 8.0+):
CREATE INDEX idx_lower_name ON users((LOWER(name)));—— 注意括号内是表达式,不是函数调用语法;查询时必须显式写出相同表达式才能走索引,例如WHERE LOWER(name) = 'alice'
ONLINE 和 ALGORITHM 参数的实际影响
MySQL 5.6+ 的 InnoDB 表支持在线创建索引,但默认行为随版本变化,不显式指定可能引发意外阻塞。
KGOGOMall 是一套采用 Php + MySql 开发的基于 WEB 应用的 B/S 架构的B2C网上商店系统。具有完善的商品管理、订单管理、销售统计、新闻管理、结算系统、税率系统、模板系统、搜索引擎优化,数据备份恢复,会员积分折扣功能,不同的会员有不同的折扣,支持多语言,模板和代码分离等,轻松创建属于自己的个性化用户界面。主要面向企业和大中型网商提供最佳保障,最大化满足客户目前及今后的独立
-
ALGORITHM=INPLACE:优先尝试原地重建,不拷贝整表,速度快、锁粒度小(仅元数据锁 + 少量行锁) -
ALGORITHM=COPY:强制全表复制重建,速度慢、锁表时间长,旧版本或某些复杂索引(如全文索引)可能退化至此 -
LOCK=NONE:允许并发 DML(INSERT/UPDATE/DELETE),但并非所有ALGORITHM都支持;INPLACE通常支持LOCK=NONE,而COPY只能LOCK=ALL - 实操建议:线上环境务必显式加参数,例如:
CREATE INDEX idx_phone ON users(phone) ALGORITHM=INPLACE LOCK=NONE;
常见失败原因和绕过方式
很多 CREATE INDEX 报错不是语法问题,而是底层约束或状态冲突。
-
ERROR 1071 (42000): Specified key was too long:字段长度超限(如VARCHAR(1000)+ utf8mb4 字符集 → 最大索引长度 3072 字节),解决方法是缩小长度或指定前缀:CREATE INDEX idx_title ON posts(title(191)); -
ERROR 1170 (42000): BLOB/TEXT column used in key specification:对TEXT或BLOB字段建索引必须指定前缀长度,例如:CREATE INDEX idx_content ON articles(content(255)); - 试图对生成列(generated column)建索引但未声明为
STORED:只有STORED列才能建索引,VIRTUAL列不行 - 表被其他会话正在执行
ALTER TABLE或长时间事务占用元数据锁,可查SELECT * FROM performance_schema.metadata_locks;确认
CREATE INDEX idx_updated_at ON logs(updated_at) USING BTREE ALGORITHM=INPLACE LOCK=NONE;
索引真正生效的关键不在“建出来”,而在查询是否能触发它。别只看 CREATE INDEX 成功就以为万事大吉——记得用 EXPLAIN 验证执行计划,尤其注意 key 和 rows 字段。联合索引顺序、字符集、隐式类型转换,都可能让刚建好的索引变成摆设。









