需为各租户单独建部分索引以实现数据隔离与性能优化:先确认tenant_id字段存在且非空,再创建含partialFilterExpression的复合索引,如{tenant_id:1,created_at:-1};为不同租户建专用索引时须用唯一名称,如idx_t1_amount,并通过explain验证索引命中。

在多租户MongoDB应用中,需为每个业务租户(如tenant_id="t1"、tenant_id="t2")单独建立仅覆盖其数据的索引,避免跨租户查询走全表扫描,同时节省内存与磁盘开销。
确认集合已含租户字段并有足够数据
检查目标集合(例如orders)中是否存在明确标识租户的字段,常用字段名包括tenant_id、org_id或customer_code;该字段必须在所有待索引文档中存在且类型一致(推荐字符串或ObjectId)。若字段缺失或值为null,后续部分索引将跳过这些文档,导致查询无法命中索引。
运行db.orders.findOne()确认结构,确保返回文档包含tenant_id:"t1"这类非空值。
创建单字段租户隔离索引
执行db.orders.createIndex({tenant_id: 1, created_at: -1}, {partialFilterExpression: {tenant_id: {$exists: true, $ne: null}}})。
该命令构建复合索引,前导字段为tenant_id,确保按租户快速分流;created_at倒序便于分页和最新订单查询。partialFilterExpression限定索引仅包含tenant_id有效值的文档——【缺少此过滤会导致索引膨胀,且无法实现租户级隔离】。
为不同租户分别建立专用索引
方法一:按租户ID前缀命名索引,显式区分作用域
db.orders.createIndex({amount: 1}, {name: "idx_t1_amount", partialFilterExpression: {tenant_id: "t1"}});
db.orders.createIndex({amount: 1}, {name: "idx_t2_amount", partialFilterExpression: {tenant_id: "t2"}})。
方法二:复用同一索引名称但使用不同过滤条件(不推荐)
MongoDB不允许同名索引共存,若执行两次相同name的createIndex,第二次会报错E11000 duplicate key;必须确保每个索引name全局唯一。
方法三:用compound + partial双保险,兼顾查询灵活性与隔离性
① 第一步:确定高频查询模式,例如t1租户常查status="paid"且amount > 100;
② 第二步:创建db.orders.createIndex({tenant_id: 1, status: 1, amount: 1}, {partialFilterExpression: {tenant_id: "t1", status: {$in: ["paid", "shipped"]}}});
③ 第三步:验证索引是否生效,执行db.orders.find({tenant_id: "t1", status: "paid", amount: {$gt: 100}}).explain("executionStats"),检查executionStats.indexName是否匹配刚建的索引名,且totalDocsExamined接近totalKeysExamined。


















