对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

使用操作拒绝筛选器阻止慢速查询

8.0版本新增。

为了防止某个操作造成过多的工作负载,可以暂时拒绝与此查询结构相关联的所有操作。为此,请使用 setQuerySettings 将此操作查询结构的 reject 字段设置为 true。被拒绝的查询结构也称为操作拒绝过滤器。

在查询规划期间,查询优化器使用查询设置作为附加输入,这样会影响为运行查询而选择的计划。

此页面上的步骤将创建一个示例集合,并使用操作拒绝过滤器阻止查询结构。

假设由于应用程序的一个查询效率低下,导致集群出现过多的工作负载。为了防止查询消耗过多的集群资源,请使用操作拒绝过滤器阻止此查询和类似的查询运行。

要识别效率低下的查询,请使用以下方法,包括:

注意

您无法在Atlas免费或 Flex 集群上设立操作拒绝过滤器。

1

运行:

// Create pizzaOrders collection db.pizzaOrders.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 19, totalNumber: 10, orderDate: ISODate( "2023-03-13T08:14:30Z" ) }, { _id: 1, type: "pepperoni", size: "medium", price: 20, totalNumber: 20, orderDate: ISODate( "2023-03-13T09:13:24Z" ) }, { _id: 2, type: "pepperoni", size: "large", price: 21, totalNumber: 30, orderDate: ISODate( "2023-03-17T09:22:12Z" ) }, { _id: 3, type: "cheese", size: "small", price: 12, totalNumber: 15, orderDate: ISODate( "2023-03-13T11:21:39.736Z" ) }, { _id: 4, type: "cheese", size: "medium", price: 13, totalNumber: 50, orderDate: ISODate( "2024-01-12T21:23:13.331Z" ) }, { _id: 5, type: "cheese", size: "large", price: 14, totalNumber: 10, orderDate: ISODate( "2024-01-12T05:08:13Z" ) }, { _id: 6, type: "vegan", size: "small", price: 17, totalNumber: 10, orderDate: ISODate( "2023-01-13T05:08:13Z" ) }, { _id: 7, type: "vegan", size: "medium", price: 18, totalNumber: 10, orderDate: ISODate( "2023-01-13T05:10:13Z" ) }] )
2

运行如下 setQuerySettings 命令,以添加带有以下字段的操作拒绝过滤器:

  • find 带有一个过滤器和一个排序,定义了查询结构。

  • $db 数据库(为查询设置)。

  • settings 拒绝查询结构。

db.adminCommand( { setQuerySettings: { find: "pizzaOrders", filter: { orderDate: { $gt: ISODate( "2023-01-20T00:00:00Z" ) } }, sort: { totalNumber: 1 }, $db: "test" }, settings: { reject: true }} )

截断的如下输出显示了 queryShapeHash 字段值,settings reject 字段为 true:

{ queryShapeHash: 'AB8ECADEE8F0EB0F447A30744EB4813AE7E0BFEF523B0870CA10FCBC87F5D8F1', settings: { reject: true }, representativeQuery: { find: 'pizzaOrders', filter: { orderDate: { '$gt': ISODate('2023-01-20T00:00:00.000Z') } }, sort: { totalNumber: 1 }, '$db': 'test' }, ok: 1, ...}
3

运行 explain:

db.pizzaOrders.explain().find( { orderDate: { $gt: ISODate("2023-01-20T00:00:00Z" ) } } ).sort( { totalNumber: 1 } )

截断的如下输出表明,querySettings reject 字段为 true:

{ queryPlanner: { winningPlan: { stage: 'SINGLE_SHARD', shards: [ { explainVersion: '1', ... namespace: 'test.pizzaOrders', parsedQuery: { orderDate: { '$gt': ISODate('2023-01-20T00:00:00.000Z') } }, querySettings: { reject: true }, ... } ] }}
4

尝试运行此查询:

db.pizzaOrders.find( { orderDate: {$gt: ISODate("2023-01-20T00:00:00Z" ) } } ).sort( { totalNumber: 1 } )

如下输出将确认查询被拒绝:

MongoServerError: Query rejected by admin query settings
5

要列出所有操作拒绝筛选器,请在聚合中使用$querySettings 和$match 阶段。在以下聚合示例中:

  • showDebugQueryShape字段在 阶段为true $querySettings,此阶段会返回查询结构的调试版本。有关详细信息,请参阅查询结构统计信息。

  • $match 阶段筛选查询设置以保留将 settings.reject设立为 true 的设置,这对应于操作拒绝筛选器。

聚合示例:

db.aggregate( [ { $querySettings: { showDebugQueryShape: true } }, { $match: { "settings.reject": true } }] )

输出:

[ { queryShapeHash: 'AB8ECADEE8F0EB0F447A30744EB4813AE7E0BFEF523B0870CA10FCBC87F5D8F1', settings: { reject: true }, representativeQuery: { find: 'pizzaOrders', filter: { orderDate: { '$gt': ISODate('2023-01-20T00:00:00.000Z') } }, sort: { totalNumber: 1 }, '$db': 'test' }, debugQueryShape: { cmdNs: { db: 'test', coll: 'pizzaOrders' }, command: 'find', filter: { orderDate: { '$gt': '?date' } }, sort: { totalNumber: 1 } } }]
6

如下示例使用 removeQuerySettings 删除操作拒绝过滤器,此过滤器由前面的第 2 步中所示的输出中的 queryShapeHash 值识别:

db.adminCommand( { removeQuerySettings: "AB8ECADEE8F0EB0F447A30744EB4813AE7E0BFEF523B0870CA10FCBC87F5D8F1"} )

也可以从以下位置获取 queryShapeHash 值:

也可以使用查询结构删除操作拒绝过滤器。例如:

db.adminCommand( { removeQuerySettings: { find: "pizzaOrders", filter: { orderDate: { $gt: ISODate( "2023-01-20T00:00:00Z" ) } }, sort: { totalNumber: 1 }, $db: "test" }} )
7

由于删除了操作拒绝过滤器,如下查询已被取消阻止,并且现在正在运行:

db.pizzaOrders.find( { orderDate: {$gt: ISODate("2023-01-20T00:00:00Z" ) } } ).sort( { totalNumber: 1 } )

使用操作拒绝过滤器阻止低效操作之后,集群性能应当恢复到引入低效查询之前的状态。后续步骤:

  1. 解决查询性能问题。这可能需要执行索引或重写查询。

  2. 部署更新后的应用程序。

要重新启用未删除的查询设置,请使用 setQuerySettings 并将 reject 字段设置为 false。