createindex调用后explain仍显示collscan,主因是索引未匹配查询:字段顺序错误(缺最左前缀)、bson类型不一致(如string与int64混用)、或mongo.indexmodel未正确配置options(如缺失.setexpireafterseconds或.setbackground)。

Go语言操作MongoDB时,索引没建对、建错时机或配错参数,查询就永远走COLLSCAN——哪怕你写了CreateIndex,也可能白忙活。
为什么CreateIndex调用了但explain还是COLLSCAN?
不是驱动没生效,而是索引根本没匹配上查询条件。常见原因有三个:
- 字段顺序错:复合索引
{"status": 1, "updated_at": -1},但查询只用了{"updated_at": {"$gt": t}},前导字段status缺失,索引被跳过 - 类型不一致:查询用
int64,但索引建在string字段上(比如"123"vs123),BSON类型不匹配导致无法命中 - 选项没传进
Options:比如设unique: true却只写了Keys,mongo.IndexModel必须显式带Options字段才生效
mongo.IndexModel怎么写才不踩坑?
别再只传bson.D{{"field", 1}}了,关键行为全靠Options控制:
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 升序/降序用
1/-1,文本索引用"text",地理索引用"2dsphere"——混用字符串和数字会静默失败 - 过期索引必须满足:字段是
Date或ObjectId类型,且Options里明确调用.SetExpireAfterSeconds(3600) - 后台建索引加
.SetBackground(true),避免阻塞读写;生产环境大集合务必加.SetMaxTime(30 * time.Second)防卡死 - 唯一索引要验证是否真生效:查
db.getCollectionInfos({name: "your_collection"})确认unique: true出现在索引定义里
建索引该放在哪?启动时还是请求里?
必须放服务启动阶段,且只能执行一次(幂等性已由驱动保证):
- 别在HTTP handler里调用
CreateIndex:它会锁表、阻塞写入,高并发下直接拖垮服务 - 重复调用
CreateIndex不报错,但MongoDB会拒绝并发建同一索引——你看到的“成功”可能只是被忽略 - 已有百万级数据时,建索引期间读写延迟上升,建议加
{background: true}并选业务低峰期操作 - 如果用
golang-migrate/migrate管理变更,迁移文件得用JSON格式,如002_create_indexes.up.json,确保上线回滚可控
索引越多越好?小心内存和写入开销
每个索引都吃RAM,还拖慢写入——这不是理论,是线上真实抖动来源:
- MongoDB把索引全放内存里,10个字段各建单索引,可能比1个三字段复合索引多占3倍内存
- 每次
Insert/Update都要同步更新所有相关索引,写入吞吐量随索引数线性下降 - 优先按
ESR规则设计:等值查询字段(Equal)放最左,接着是排序字段(Sort),最后是范围字段(Range)——比如{"tenant_id": 1, "created_at": -1, "status": 1} - 用
explain("executionStats")验证:看executionStages.nReturned是否接近totalDocsExamined,若二者接近说明索引没起作用
真正卡住性能的,往往不是没建索引,而是建了但字段顺序不对、类型不匹配、或者压根没验证是否命中。每次改索引后,必须跑一遍explain,盯着stage字段看是不是IXSCAN——其他都是幻觉。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










