View a markdown version of this page

查询规划器 v3 - Amazon DocumentDB

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

查询规划器 v3

Amazon DocumentDB 8.0 中的 Planner 版本 3 支持 21 个聚合阶段,包括 6 个新阶段。Planner V3 内置了对不同命令的支持。与亚马逊 DocumentDB 5.0 中的 Planner v2 相比,它的总体性能提高了多达 2 倍。亚马逊 DocumentDB 8.0 中的所有新功能和运算符都与 Planner v3 兼容。Planner v3 支持的亚马逊 DocumentDB 8.0 中的新聚合阶段包括 $replaceWith、$VectorSearch、$merge、$set、$set、$unset、$bucket。Planner v3 还支持 Amazon DocumentDB 8.0 中的新功能和运算符,包括 Collation、Views、$merge、$pow、$rand、$dateTrunc、$date、$date、$date。ToParts FromParts

先决条件

以下先决条件适用于规划器版本 3.0:

  • Planner 版本 3.0 在所有引擎版本 8.0 可用 AWS 区域 的地方都可用。

  • 选择引擎版本 8.0 时,计划器版本 3.0 是默认的查询计划器。

选择计划器版本 3.0 作为默认查询计划器

如果您在 Amazon DocumentDB 8.0 中更改了默认查询计划器,并且需要恢复到计划器 v3,则可以通过控制台或 CLI 执行此操作:

  • 按照 修改 Amazon DocumentDB 集群参数 中的步骤修改集群的参数组。

  • 对于标题为 “规划器版本” 的参数,将值更改为 3.0,表示计划器版本 3.0。

  • 选择立即应用(若选择重启时应用,则在集群下次重启后才会生效)。

最佳实践

要获得预期结果,请在应用规划器版本 3.0 时使用以下最佳实践:

  • 在全局群集中,在两个区域的群集参数组中选择相同的plannerVersion值(1.0 或 2.0 或 3.0)。请注意,在主要和次要区域中选择不同的计划器版本可能会导致查询行为和性能不一致。

  • 在定期维护时段或减少流量期间更新到 Planner 版本 3.0 的干扰最小,因为如果在工作负载活跃运行时更改计划器版本,错误率可能会增加。

限制

以下限制适用于规划器版本 3.0:

  • 弹性集群不支持规划器版本 3.0,它将回落到规划器版本 1.0。

  • 虽然 Planner v1 允许使用 “PlanHint” 来确保查询优化器选择特定的查询计划,但 Planner v3 不允许使用 “PlanHint”,而是依靠内部优化来为给定查询选择最佳计划。

对聚合和区分运算符的改进

规划师版本 3.0 引入了对 $aggregate 阶段和 $distinct 命令的改进。以下是一些最值得注意的改进...

  • 计划者尽可能将$match阶段移到管道的早期阶段,从而减少后续阶段处理的文档数量。

    //Planner v1 db.orders.aggregate([ { $project: { customerId: 1, orderDate: 1, totalAmount: 1 } }, { $match: { customerId: { $gt: 1000 } } } ]) // Planner v3 pulls up the match since customerId exists in original documents // Optimized internally as: db.orders.aggregate([ { $match: { customerId: { $gt: 1000 } } }, // Pulled up before project { $project: { customerId: 1, orderDate: 1, totalAmount: 1 } } ])
  • 当 $lookup 和 $unwind 阶段在同一个字段上运行时,规划器会自动将其组合在一起,从而减少中间数据处理并提高性能。

    Example query: //Planner v1 db.orders.aggregate([ { $lookup: { from: "products", localField: "productId", foreignField: "_id", as: "productInfo" } }, { $unwind: "$productInfo" }, { $project: { orderDate: 1, "productInfo.name": 1, "productInfo.price": 1 } } ]) // Planner version 3.0 optimizes this internally by coalescing the $lookup and $unwind stages
  • Planner 版本 3.0 引入了新的 Distinct Scan 执行策略,该策略显著提高了对低基数索引进行不同操作的性能。

    Example query: //// If there is a low cardinality index on "category", you may see a query plan like below db.explain().products.distinct("category") "queryPlanner" : { "plannerVersion" : 3, "namespace" : "db.products", "winningPlan" : { "stage" : "AGGREGATE", "inputStage" : { "stage" : "DISTINCT_SCAN", "inputStage" : { "stage" : "IXONLYSCAN", "indexName" : "category_1", "direction" : "forward" } } } }

规划缓存过滤器

Planner 版本 3.0 支持计划缓存过滤器,也称为索引过滤器,它允许您限制计划器为特定查询形状考虑的索引集。过滤器使用数据库命令设置并应用到服务器上,因此,如果您遇到查询回归,则无需修改应用程序代码即可缓解查询回归。

规划器版本 3.0 将计划缓存过滤器应用于比计划器版本 2.0 更多的命令:

  • 该distinct命令需要计划器版本 3.0。

  • 该aggregate命令需要计划器版本 3.0 和 Amazon DocumentDB 8.0.2。当管道通过前导$match阶段读取集合时,过滤器适用。

  • 在$lookup或$graphLookup阶段的外部集合上设置的过滤器驱动用于扫描该外国集合的索引。这还需要计划器版本 3.0 和 Amazon DocumentDB 8.0.2。

有关命令参考、支持的查询形状、工作示例以及过滤器如何与提示交互的更多信息,请参阅规划缓存过滤器。

规划器版本 1.0、3.0 和 MongoDB 之间的潜在行为差异

在某些极端情况下,计划器版本 3.0 产生的结果可能与计划器版本 1.0 略有不同。本节将介绍这些可能性的一些示例。

Feature Differences
  • 在空集合中,或者当匹配等前几个阶段筛选所有文档时,Planner v1 给出输出 “字段”: 0。Planner v3 和 MongoDB 不会给出任何输出。

  • 在 Plannerv1 中,如果上一阶段返回的文档少于 n 个,{"$skip”: n} 不会跳过。无论返回的文档数量多少,Plannerv3 和 MongoDB 都能正确跳过。

  • 当 $lookup 中引用的外国集合不存在时,plannerv1 会引发错误。Planner v3 和 MongoDB 将外国集合视为空集合并执行 $lookup。

    db.coll.aggregate([ {$lookup: {from: "does_not_exist", localField: "a", foreignField: "a", as: "c"}} ])
  • 只有 Planner v1 允许在管道中使用多个 $search 计划器 v2/v3 会引发错误,而 MongoDB 不支持它。

    VectorSearch = { "$search": { "vectorSearch": { "vector": [0.2, 0.5, 0.8], "path": "vectorEmbedding", "similarity": "cosine", "k": 2, "efSearch": 1 }}} db.coll.aggregate([VectorSearch, VectorSearch])
  • 当 VectorSearch 阶段不是第一阶段时,只有 Planner v3 才有效。在这种情况下,MongoDB 将引发错误,并且 Planner v1 不支持 $vectorSearch 阶段。

    VectorSearch = { {"$vectorSearch": { "queryVector": [0.2, 0.5, 0.8], "path": "vectorEmbedding", "similarity": "euclidean", "limit": 4, "numCandidates": 100} } db.coll.aggregate([$match:{}, VectorSearch])