You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB $lookup是否使用foreignField索引?示例未生效原因咨询

MongoDB $lookup 与 foreignField 索引使用问题

1. MongoDB的$lookup操作是否会使用foreignField字段对应的索引?

MongoDB的$lookup可以使用foreignField对应的索引,但并非一定会用——查询优化器会根据数据集大小、查询成本等因素判断,只有当使用索引能显著提升效率时,才会选择利用索引进行关联查询。

2. 示例中inventory集合的sku字段索引为何未被使用?

示例代码

db.orders.insertMany( [
   { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
   { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },
   { "_id" : 3  }
] )

db.inventory.insertMany( [
   { "_id" : 1, "sku" : "almonds", "description": "product 1", "instock" : 120 },
   { "_id" : 2, "sku" : "bread", "description": "product 2", "instock" : 80 },
   { "_id" : 3, "sku" : "cashews", "description": "product 3", "instock" : 60 },
   { "_id" : 4, "sku" : "pecans", "description": "product 4", "instock" : 70 },
   { "_id" : 5, "sku": null, "description": "Incomplete" },
   { "_id" : 6 }
] )

db.orders.aggregate( [
   {
     $lookup:
       {
         from: "inventory",
         localField: "item",
         foreignField: "sku",
         as: "inventory_docs"
       }
  }
] )

执行计划(explain结果)

{
    "explainVersion" : "1",
    "stages" : [
        {
            "$cursor" : {
                "queryPlanner" : {
                    "namespace" : "6303c64faf8ef53d8ba2062f_y22_test2.orders",
                    "indexFilterSet" : false,
                    "parsedQuery" : {

                    },
                    "queryHash" : "8B3D4AB8",
                    "planCacheKey" : "D542626C",
                    "maxIndexedOrSolutionsReached" : false,
                    "maxIndexedAndSolutionsReached" : false,
                    "maxScansToExplodeReached" : false,
                    "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "direction" : "forward"
                    },
                    "rejectedPlans" : [

                    ]
                }
            }
        },
        {
            "$lookup" : {
                "from" : "inventory",
                "as" : "inventory_docs",
                "localField" : "item",
                "foreignField" : "sku"
            }
        }
    ]
}

索引未被使用的原因

  1. 数据集过小:inventory集合仅包含6条文档,全表扫描的开销远低于通过索引查找文档的开销(索引需要先遍历索引条目,再回表查询文档),优化器自然选择更高效的全表扫描。
  2. 空值/缺失字段的关联逻辑:orders集合存在item字段缺失的文档(_id:3),inventory集合存在sku为null(_id:5)和sku缺失(_id:6)的文档。当关联值为null或字段缺失时,MongoDB需要匹配所有foreignField为null或缺失的文档,这种场景下全表扫描比索引查询更直接高效。
  3. 优化器成本评估:从explain输出可以看到,$lookup阶段未触发索引使用,说明优化器通过成本计算后,认为全表扫描是当前最优的执行路径。

内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:05:18