查询计划


进入MongoDB中文手册(4.2版本)目录

对于查询,MongoDB查询优化器会根据可用索引选择并缓存最有效的查询计划。当查询计划程序评估候选的计划时,基于查询执行计划执行的“工作单元”(works)的数量评估出最有效的查询计划。
关联的计划缓存条目用于后续的具有相同查询形状(query shape)的查询。

1 计划的缓存条目状态(Cache Entry State)

从MongoDB 4.2开始,缓存条目与状态关联:

状态描述
Missing缓存中不存在此形状的条目。

对于查询,如果一个形状的缓存条目状态为 Missing:
 1. 评估候选计划并选择优选的计划。
 2. 所选计划将以Inactive状态和其works值添加到缓存中。
Inactive缓存中的条目是查询形状的占位符条目。也就是说,计划程序已经看到了形状并计算了其代价(works值)并存储为占位符条目,但查询形状不用于生成查询计划。

对于查询,如果形状的缓存条目状态时Inactive:
 1. 评估候选计划并选择优选的计划。
 2. 将所选计划的works值与Inactive条目的值进行比较。如果所选计划的works值为:
  * 小于或等于Inactive条目的值,
   所选计划将替换占位符“Inactive”条目,并具有“ Active”状态。
   如果在替换发生之前,“ Inactive”条目变为“ Active”(例如,由于另一个查询操作),则仅当新活动条目的works值大于所选计划时,才会替换新活动条目。

  * 大于Inactive条目的数量,
   Inactive条目保留,但其works值增加。
Active缓存中的条目用于优选的计划。计划程序可以使用该条目来生成查询计划。

对于查询,如果形状的缓存条目状态为 Active:
 1. Active条目用于生成查询计划。
 2. 计划程序还评估条目的性能,如果条目的 works值不再符合选择标准,它将转换为Inactive状态。

有关触发对计划缓存进行更改的其他方案,请参阅计划缓存刷新。

1.1 查询计划和缓存信息

要查看给定查询的查询计划信息,可以使用 db.collection.explain()或cursor.explain()。
从MongoDB 4.2开始,您可以使用$planCacheStats 聚合阶段来查看集合的计划缓存信息。

1.2 计划缓存刷新

如果mongod 重新启动或关闭,查询计划缓存将不会保留。此外:

  • 删除索引或集合这样的目录操作(Catalog operations)会清除计划缓存。
  • 最近最少使用(LRU)缓存替换机制将清除最近最少访问的缓存条目,无论状态如何。

用户还可以:

  • 使用PlanCache.clear()方法手动清除整个计划缓存 。
  • 使用PlanCache.clearPlansByQuery()方法手动清除特定的计划缓存条目 。

2 queryHash和planCacheKey

2.1 queryHash

为了帮助识别具有相同查询形状的慢查询,从MongoDB 4.2开始,每个查询形状都与一个queryHash关联。queryHash是代表查询形状的一个hash,并且仅依赖于所述查询形状的十六进制字符串。

注意
与任何哈希函数一样,两个不同的查询形状可能会导致相同的哈希值。但是,不同查询形状之间不会发生哈希冲突。

2.2 planCacheKey

为了提供对查询计划缓存的更多了解,MongoDB 4.2引入了planCacheKey。
planCacheKey 是与查询关联的计划缓存条目的键的哈希值。

注意
不同于queryHash,planCacheKey是查询形状和该形状当前可用索引的函数。即,如果添加/删除了可以支持查询形状的索引,则该planCacheKey值可能会更改,而该 queryHash值不会更改。

例如,考虑具有以下索引的foo集合:

db.foo.createIndex( { x: 1 } )
db.foo.createIndex( { x: 1, y: 1 } )
db.foo.createIndex( { x: 1, z: 1 }, { partialFilterExpression: { x: { $gt: 10 } } } )

集合上的以下查询具有相同的形状:

db.foo.explain().find( { x: { $gt: 5 } } )  // 查询操作 1
db.foo.explain().find( { x: { $gt: 20 } } ) // 查询操作 2

给定这些查询,具有部分过滤器表达式(partial filter expression)的索引可以支持查询操作2,但不支持查询操作1。由于可用于支持查询操作1的索引不同于查询操作2,因此两个查询具有不同的 planCacheKey。
如果删除了一个索引,或者添加了新索引{ x: 1, a: 1 },则两个查询操作的都会更改planCacheKey。

2.3 可用性

queryHash和planCacheKey在用于:

  • explain()输出字段: queryPlanner.queryHash和queryPlanner.planCacheKey;
  • 记录慢查询时,分析器日志消息诊断日志消息(即mongod / mongos日志消息)
  • $planCacheStats聚合阶段(MongoDB 4.2中的新增功能);
  • PlanCache.listQueryShapes()方法和planCacheListQueryShapes命令;
  • PlanCache.getPlansByQuery() 方法和planCacheListPlans命令。

3 索引过滤器

索引过滤器确定优化器为查询形(query shape)状评估的索引 。查询形状由查询,排序和投影规范的组合而成。如果给定查询形状存在索引过滤器,那么优化器仅考虑过滤器中指定的那些索引。
当查询形状存在索引过滤器时,MongoDB将忽略 hint()。要查看MongoDB是否对查询形状应用了索引过滤器,请使用db.collection.explain()cursor.explain()方法的indexFilterSet字段检查。
索引过滤器仅影响优化器评估的索引;优化器仍然可以选择将集合扫描作为给定的查询形状的优选的计划。
索引过滤器在服务器进程的持续时间内存在,并且在关闭后不会持续存在。MongoDB还提供了手动删除过滤器的命令。
因为索引过滤器会覆盖优化器和hint()方法的预期行为,所以请谨慎使用索引过滤器。
请参见planCacheListFiltersplanCacheClearFiltersplanCacheSetFilter

也可以看看:索引策略

进入MongoDB中文手册(4.2版本)目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值