首页/数据/NoSQL 速查/createIndex 创建索引
MongoDB99 条

createIndex 创建索引

索引创建语法 createIndex(keys, options):keys 描述字段与方向,options 可命名、加唯一约束或特殊类型;构建期间业务一般可继续读写。

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

createIndex 是什么

createIndex(keys, options) 为集合建立索引:keys 描述字段与方向(1 升序、-1 降序,或 text、hashed、2dsphere 等类型),options 用于命名、加唯一约束、限制部分文档或设置过期时间。索引让查询从全集合扫描变成按索引定位,代价是写入变慢与额外存储。构建期间业务一般可以继续读写,但大集合上会明显占用 IO。

基本信息

语法db.collection.createIndex({ field: 1 }, options)
方向与类型1 / -1 / "text" / "hashed" / "2dsphere" / "2d"
常用选项name / unique / sparse / partialFilterExpression / expireAfterSeconds / collation
复合索引字段顺序决定前缀可用性
构建影响占用 IO 与磁盘临时空间,业务低峰期执行
查看现状db.collection.getIndexes()

典型使用场景

  • 高频等值查询字段(订单号、用户 ID)建单字段索引
  • 复合查询条件按「等值在前、范围在后」建复合索引
  • 唯一约束:用户名、手机号等业务唯一键加 unique
  • 过期数据自动清理:会话表加 expireAfterSeconds 做 TTL 索引
  • 只索引部分文档:用 partialFilterExpression 减少索引体积
  • 全文检索:给描述字段建 text 索引支持 $text 查询

示例

示例
db.orders.createIndex({ status: 1, ts: -1 }, { name: "status_ts" })        # 复合索引
db.orders.createIndex({ orderNo: 1 }, { unique: true })                    # 唯一索引
db.sessions.createIndex({ expireAt: 1 }, { expireAfterSeconds: 3600 })     # TTL 索引
db.orders.createIndex({ status: 1, ts: -1 }, { partialFilterExpression: { status: "paid" } })  # 部分索引
db.products.createIndex({ title: "text" }, { default_language: "none" })   # 全文索引
db.orders.getIndexes()                                                    # 查看已有索引

常用选项读法

选项作用使用注意
name显式命名索引便于后续 drop 与巡检
unique唯一性约束已有重复数据时创建失败
sparse跳过缺失该字段的文档默认索引会包含 null
partialFilterExpression只索引满足条件的文档比 sparse 更精确也更省空间
expireAfterSeconds按时间自动过期删除仅单字段日期索引可用
collation指定排序规则大小写不敏感查询需要一致设置
索引构建进度可用 db.currentOp() 或 db.adminCommand({ currentOp: 1 }) 观察;构建完成后用 explain 验证查询是否真的走上索引。
给已经存在重复数据的字段加唯一索引会构建失败,先清理重复再建,或用 partialFilterExpression 收窄范围。

索引设计要点

  • 查询的过滤字段、排序字段、覆盖字段决定了该建什么索引
  • 复合索引字段顺序要与最常用查询的条件顺序一致
  • 低选择性字段(如只有几个取值的状态)单独建索引收益有限
  • 一个集合索引不宜过多,每个索引都会放大写入成本
  • 排序方向要与索引方向一致,否则仍需内存排序
  • 定期用 $indexStats 找出从未被使用的索引并清理

索引维护与清理

  • 滚动建索引更稳妥:先在从节点建好,再逐步切换主节点
  • 用 $indexStats 看索引被访问次数,长期为零的索引可评估下线
  • 删索引用 dropIndex(name) 前先确认没有查询依赖它
  • 改索引定义优先「先建新再删旧」,避免中间出现无索引窗口
  • 索引占用用 db.collection.stats() 的 indexSizes 查看
  • 哈希索引只支持等值匹配,适合分片键,范围查询要用普通索引
构建索引会与写入争抢 IO:安排到业务低峰期,构建期间用 db.currentOp() 观察进度,不要中途重启实例。
分片集合上的唯一索引有限制:分片键必须包含在唯一索引字段中,否则无法创建,规划分片键时就要把唯一性需求考虑进去。
TTL 索引的删除由后台线程按分钟级调度,不会精确到过期时刻;需要严格按时清理的场景应另设计清理任务。
索引命名建议带上字段与方向(如 status_1_ts_-1),系统默认名称在字段较多时难以辨认,巡检与删除都容易认错。

易错点

  • 业务高峰期建索引会挤占 IO:大集合构建期间查询变慢,安排在低峰并观察进度
  • 同一字段组合重复建索引只会放大写放大与存储,建前先 getIndexes 检查现状
  • 加了 unique 但集合中已有重复值,创建直接失败并给出重复键样例,需要先清洗数据
  • 复合索引字段顺序写反(如把状态放最前再放时间)会导致部分查询无法用索引
  • TTL 索引依赖后台线程每分钟扫描一次,删除不是精确到秒,别把它当定时任务使用

数据来源与参考

  • MongoDB Manual: db.collection.createIndex()
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌