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" } } ] }
索引未被使用的原因
- 数据集过小:inventory集合仅包含6条文档,全表扫描的开销远低于通过索引查找文档的开销(索引需要先遍历索引条目,再回表查询文档),优化器自然选择更高效的全表扫描。
- 空值/缺失字段的关联逻辑:orders集合存在
item字段缺失的文档(_id:3),inventory集合存在sku为null(_id:5)和sku缺失(_id:6)的文档。当关联值为null或字段缺失时,MongoDB需要匹配所有foreignField为null或缺失的文档,这种场景下全表扫描比索引查询更直接高效。 - 优化器成本评估:从explain输出可以看到,$lookup阶段未触发索引使用,说明优化器通过成本计算后,认为全表扫描是当前最优的执行路径。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

