Mongodb聚合:$planCacheStats

执行查询时,MongoDB 查询规划器会根据可用索引选择并缓存效率最高的查询计划。$planCache可以返回所有集合的查询计划缓存信息。要使用$planCache,必须把$planCacheStats阶段放在管道最前面。

语法

js 复制代码
{ $planCacheStats: { } }

使用

  • $planCacheStats必须是管道的第一个阶段
  • $planCacheStats不能应用于事务和$facet阶段
  • $planCacheStats需要的读关注级别为"local"
  • 如果系统启用了权限控制,用户必须要有对集合的planCacheRead授权
  • 当使用查询加密,$planCacheStats阶段会忽略对加密集合的操作,即便是操作被正常缓存。

读取偏好

$planCacheStats在选择返回计划缓存信息的主机时,会遵守读取偏好。

应用程序可能以副本集的不同成员为目标。因此,每个副本集成员可能会收到不同的读取命令,并拥有与其他成员不同的计划缓存信息。尽管如此,在副本集或分片集群上运行$planCacheStats仍会遵守正常的读取优先规则。也就是说,在副本集上,该操作只从副本集的一个成员处收集计划缓存信息;在分片集群上,该操作只从每个分片副本集的一个成员处收集计划缓存信息。

输出

$planCacheStats的输出取决于完成查询所使用的查询引擎,version字段的值表明使用了哪个查询引擎:

  • 1表示使用了经典引擎。
  • 2表示使用了基于时隙的查询执行引擎。
经典执行引擎

对于使用经典执行引擎的查询,$planCacheStats会返回与下面类似的文档:

json 复制代码
{
   "version" : 1,
   "createdFromQuery" : <document>,
   "queryHash" : <hexadecimal string>,
   "planCacheKey" : <hexadecimal string>,
   "isActive" :  <boolean>,
   "works" : <NumberLong>,
   "cachedPlan" : {
      "stage" : <STAGE1>,
      "filter" : <document>,
      "inputStage" : {
         "stage" : <STAGE2>,
         ...
      }
   },
   "timeOfCreation" : <date>,
   "creationExecStats" : [   //每个候选计划的执行统计文档
      {
         "nReturned" : <num>,
         "executionTimeMillisEstimate" : <num>,
         "totalKeysExamined" : <num>,
         "totalDocsExamined" :<num>,
         "executionStages" : {
            "stage" : <STAGE A>,
            ...
            "inputStage" : {
               "stage" : <STAGE B>,
               ...
            }
         }
      },
      ...
   ],
   "candidatePlanScores" : [
      <number>,
      ...
   ],
   "indexFilterSet" : <boolean>,
   "estimatedSizeBytes" : <num>,
   "host" : <string>,
   "shard" : <string>
}

对于使用基于slot的查询执行引擎的查询,$planCacheStats会返回与下面类似的文档:

json 复制代码
{
   "version" : 2,
   "queryHash" : <hexadecimal string>,
   "planCacheKey" : <hexadecimal string>,
   "isActive" :  <boolean>,
   "works" : <NumberLong>,
   "cachedPlan" : {
      "slots" : <string>,
      "stages": <string>
   },
   "indexFilterSet" : <boolean>,
   "estimatedSizeBytes" : <num>,
   "host" : <string>
}

每份文档都包含各种查询计划和执行统计信息,包括:

字段 说明
version 查询引擎的版本号,1为经典引擎,2为基于slot的执行引擎
createdFromQuery 一个包含了产生该缓存条目的特定查询的文档
isActive 布尔值,表示是否处于活动状态,如果为true,表示查询规划器当前正在使用它产生查询计划;如果为false,则表示查询规划期当前没有使用它
queryHash 一个16进制格式的字符串,就是查询模型的哈希值
works 查询规划器评估候选计划的试运行期间查询执行计划执行的 "工作单元 "数量
timeOfCreation 创建条目的时间
creationExecStats 执行统计文档数组。该数组包含每个候选计划的文档
candidatePlanScores creationExecStats数组中列出的候选计划的得分数组
indexFilterSet 布尔值,表示查询形状是否存在索引过滤器
estimatedSizeBytes 计划缓存条目的估计大小(字节)
host mongod实例的主机名和端口号。当运行于分片集群时,操作返回每个分片副本集的信息,并使用分片和主机字段进行区分
shard 分片名称,仅在分片集群上运行时可用

举例

下面的例子使用orders集合:

json 复制代码
db.orders.insertMany( [
   { "_id" : 1, "item" : "abc", "price" : NumberDecimal("12"), "quantity" : 2, "type": "apparel" },
   { "_id" : 2, "item" : "jkl", "price" : NumberDecimal("20"), "quantity" : 1, "type": "electronics" },
   { "_id" : 3, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : 5, "type": "apparel" },
   { "_id" : 4, "item" : "abc", "price" : NumberDecimal("8"), "quantity" : 10, "type": "apparel" },
   { "_id" : 5, "item" : "jkl", "price" : NumberDecimal("15"), "quantity" : 15, "type": "electronics" }
] )

在集合上创建以下索引:

js 复制代码
db.orders.createIndex( { item: 1 } );
db.orders.createIndex( { item: 1, quantity: 1 } );
db.orders.createIndex( { quantity: 1 } );
db.orders.createIndex( { quantity: 1, type: 1 } );
db.orders.createIndex(
   { item: 1, price: 1 },
   { partialFilterExpression: { price: { $gte: NumberDecimal("10")} } }
);

其中,索引{ item:1, price: 1 }是部分索引,仅索引价格字段大于或等于NumberDecimal("10")的文档。

运行下面的查询:

js 复制代码
db.orders.find( { item: "abc", price: { $gte: NumberDecimal("10") } } )
db.orders.find( { item: "abc", price: { $gte: NumberDecimal("5") } } )
db.orders.find( { quantity: { $gte: 20 } } )
db.orders.find( { quantity: { $gte: 5 }, type: "apparel" } )

上面的查询是通过基于slot的查询执行引擎完成的。

返回查询缓存中所有条目的信息

下面的聚合管道使用$planCacheStats返回集合的计划缓存条目信息:

js 复制代码
db.orders.aggregate( [
   { $planCacheStats: { } }
] )

输出:

js 复制代码
[
  {                                             
    version: '2',
    queryHash: '478AD696',
    planCacheKey: '21AE23AD',
    isActive: true,
    works: Long("7"),
    timeOfCreation: ISODate("2023-05-22T20:33:49.031Z"),
    cachedPlan: {
      ...
    },
    indexFilterSet: false,
    isPinned: false,
    estimatedSizeBytes: Long("8194"),
    host: 'mongodb1.example.net:27018'
  },
  {                                            
       version: '2',
       queryHash: '3D8AFDC6',
       planCacheKey: '1C2C4360',
       isActive: true,
       works: Long("6"),
       timeOfCreation: ISODate("2023-05-22T20:33:50.584Z"),
       cachedPlan: {
         ...
       },
       indexFilterSet: false,
       isPinned: false,
       estimatedSizeBytes: Long("11547"),
       host: 'mongodb1.example.net:27018'
     },
     {                                          
       version: '2',
       queryHash: '27285F9B',
       planCacheKey: '20BB9404',
       isActive: true,
       works: Long("1"),
       timeOfCreation: ISODate("2023-05-22T20:33:49.051Z"),
       cachedPlan: {
         ...
       },
       indexFilterSet: false,
       isPinned: false,
       estimatedSizeBytes: Long("7406"),
       host: 'mongodb1.example.net:27018'
     },
     {                                          
       version: '2',
       queryHash: '478AD696',
       planCacheKey: 'B1435201',
       isActive: true,
       works: Long("5"),
       timeOfCreation: ISODate("2023-05-22T20:33:49.009Z"),
       cachedPlan: {
         ...
       },
       indexFilterSet: false,
       isPinned: false,
       estimatedSizeBytes: Long("7415"),
       host: 'mongodb1.example.net:27018'
     }
   ],

查找查询哈希缓存详情

要返回特定查询散列的计划缓存信息,可使用$planCacheStats阶段后,可以在planCacheKey字段上添加$match

以下聚合管道使用$planCacheStats之后的$match阶段来返回特定查询散列的特定信息:

js 复制代码
db.orders.aggregate( [
   { $planCacheStats: { } },
   { $match: { planCacheKey: "B1435201"} }
] )

输出:

js 复制代码
[
  {
    version: '2',
    queryHash: '478AD696',
    planCacheKey: 'B1435201',
    isActive: true,
    works: Long("5"),
    timeOfCreation: ISODate("2023-05-22T20:33:49.009Z"),
    cachedPlan: {
      slots: '$$RESULT=s11 env: { s3 = 1684787629009 (NOW), s6 = Nothing, s5 = Nothing, s1 = TimeZoneDatabase(Asia/Kuwait...Etc/UCT) (timeZoneDB), s10 = {"item" : 1, "price" : 1}, s2 = Nothing (SEARCH_META) }',
      stages: '[2] nlj inner [] [s4, s7, s8, s9, s10] \n' +
        '    left \n' +
        '        [1] cfilter {(exists(s5) && exists(s6))} \n' +
        '        [1] ixseek s5 s6 s9 s4 s7 s8 [] @"358822b7-c129-47b7-ad7f-40017a51b03c" @"item_1_price_1" true \n' +
        '    right \n' +
        '        [2] limit 1 \n' +
        '        [2] seek s4 s11 s12 s7 s8 s9 s10 none none [] @"358822b7-c129-47b7-ad7f-40017a51b03c" true false \n'
    },
    indexFilterSet: false,
    isPinned: false,
    estimatedSizeBytes: Long("7415"),
    host: 'mongodb1.example.net:27018'
  }
]
相关推荐
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
yyuuuzz7 小时前
独立站的技术基础与常见运维问题
大数据·运维·服务器·网络·数据库·aws
来杯@Java8 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记9 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
键盘上的猫头鹰10 小时前
【MySQL 教程(八)】索引、事务、用户管理、导入导出与分页查询
数据库·python·mysql
Royzst10 小时前
数据库知识点
数据库
雪的季节11 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt
宋浮檀s11 小时前
应急响应——Web漏洞:命令执行+SSRF+弱口令
运维·数据库·sql·网络安全·oracle·应急响应
云烟成雨TD12 小时前
Spring AI 1.x 系列【33】RAG Advisor 组件与四大分层架构
java·人工智能·spring
yurenpai(27届找实习中)12 小时前
redis_点评(21.好友关注——关注、取关功能实现;共同关注功能实现)
数据库·redis·缓存