首页/数据/SQL 速查/CREATE INDEX 基础写法
变更与事务52 条

CREATE INDEX 基础写法

建索引的常规语法与命名:单列、复合列顺序、唯一索引与删除索引;大表操作前先查看现有索引避免重复。

SQL 速查数据更新于 2026-10-13

CREATE INDEX 是什么

CREATE INDEX 为表建立索引,支持单列、复合列与唯一索引,也可以用 ALTER TABLE ADD INDEX 把索引变更与其他表变更写在一起。落地时要把三件事定清楚:命名规范(统一前缀加表名与列名)、列顺序(等值过滤列在前,范围与排序列在后)、建前先查现有索引避免重复。大表建索引还要考虑锁与在线 DDL 的影响,别在高峰期动手。

基本信息

适用平台MySQL 8.0 / PostgreSQL / SQL Server / Oracle
MySQL 语法CREATE INDEX idx_name ON 表 (列…);ALTER TABLE 表 ADD INDEX idx_name (列…)
删除差异MySQL 要写 DROP INDEX 索引名 ON 表名;PostgreSQL 只写 DROP INDEX 索引名
命名规范统一前缀 idx_ / uk_ + 表名 + 列名,便于检索、治理与删除
唯一索引同时承担约束语义:写入重复值会失败
在线建索引PostgreSQL 用 CREATE INDEX CONCURRENTLY;MySQL InnoDB 8.0 支持在线 DDL

典型使用场景

  • 给慢查询的过滤列补索引,减少扫描行数
  • 给排序列建索引,消除 filesort 与临时排序
  • 用唯一索引做业务约束(邮箱、编号、单据号)
  • 建复合索引支撑最左前缀查询,一条索引覆盖多种查询形态
  • 覆盖索引把查询需要的列都放进索引,避免回表
  • 配合不可见索引或部分索引做上线前的灰度验证

MySQL 写法

MySQL 写法
CREATE INDEX idx_user_created ON orders (user_id, created_at);   # 等值列在前,范围列在后
CREATE UNIQUE INDEX uk_email ON users (email);                    # 唯一索引兼做业务约束
ALTER TABLE orders ADD INDEX idx_status (status);                 # 与其他表变更合并提交
DROP INDEX idx_status ON orders;                                 # MySQL 删索引必须带表名
SHOW INDEX FROM orders;                                           # 建之前先看已有索引,避免重复

PostgreSQL 写法

PostgreSQL 写法
CREATE INDEX idx_user_created ON orders (user_id, created_at);
CREATE UNIQUE INDEX uk_email ON users (email);
DROP INDEX idx_user_created;                 -- PG 不需要表名

-- 大表在线建索引,尽量不长时间阻塞写入(不能在事务块内执行)
CREATE INDEX CONCURRENTLY idx_orders_status ON orders (status);

-- 确认索引是否建好、是否有效
SELECT indexrelid::regclass, indisvalid FROM pg_index
WHERE indrelid = 'orders'::regclass;

建索引的四个关键点

关键点做法原因
命名前缀 + 表名 + 列名便于治理、排查与后续删除
列顺序等值列在前,范围与排序列在后最左前缀决定索引能否被复用
重复检查建前 SHOW INDEX 或 \d 表名冗余索引会拖慢写入却没有收益
唯一与普通需要约束语义就用唯一索引唯一索引同时承担数据校验职责
大表执行时机低峰执行;PG 用 CONCURRENTLY减少锁等待与写入抖动
索引不是越多越好:每个索引都要在写入时同步维护,冗余与长期未使用的索引会明显拖慢插入与更新,建议定期用索引使用情况视图做一次清理评估。
PostgreSQL 的 CREATE INDEX CONCURRENTLY 失败会留下 INVALID 索引:它不会被查询使用却仍消耗写入成本,必须删除后重建;执行前确认没有长事务,否则它会一直等待。

易错点

  • 建索引时不写名字,自动生成的名字难以治理,后续删除与排查都费劲
  • 同一列重复建索引,写入成本增加却没有查询收益
  • 复合索引列顺序写反(范围列放在等值列之前),等值查询无法有效使用索引
  • 业务高峰期直接对大表建索引,长时间持锁导致写入抖动甚至超时
  • DROP INDEX 时忘了 MySQL 需要带表名,脚本报语法错误

数据来源与参考

  • MySQL 8.0 Reference Manual · CREATE INDEX Statement
  • PostgreSQL Documentation · CREATE INDEX
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌