

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

# 长时间运行的查询
<a name="anti-pattern-long-running-queries"></a>

## 概述
<a name="long-queries-overview"></a>

Long-running 查询可能会级联成群集范围的性能问题。这些查询可能会干扰 Amazon DocumentDB 的并 Multi-Version 发控制 (MVCC) 垃圾收集流程，从而导致旧版本文档积累并降低整个集群的性能。Amazon DocumentDB 实施了 2 小时的服务器端超时作为一种安全机制，以无限期限制失控的查询消耗资源。

**什么是长时间运行的查询：**
+ 长时间执行的查询（通常大于 30 分钟）
+ 打开保持活动状态数小时的游标（如果光标处于活动状态，则不适用 2 小时的超时时间）

## 对集群的影响
<a name="long-queries-impact"></a>

**长时间运行的查询可能会干扰垃圾收集进程**
+ **旧版本累积**：垃圾收集器无法回收旧文档版本
+ **集合和索引膨胀**：集合和索引条目会随着时间的推移而累积，膨胀会增加，这可能会导致更多的存储成本。
+ **CPU 和内存压力**：由于处理越来越多的旧文档版本、索引条目和事务 ID 的效率低下，CPU 和内存压力增加。

长时间运行的查询 → 阻止 GC → 存储增长 → CPU 和内存压力 → 更多长查询

## 监控和检测
<a name="long-queries-monitoring"></a>

**1。要查找长时间运行的查询，请使用 currentOp 命令。**

```
// To find a query running for more than 30 mins
db.adminCommand({
    aggregate: 1,
    pipeline: [
        {$currentOp: {}},
        {$match: 
            {$or: 
                [{secs_running: {$gt: 1800}},
                 {WaitState: {$exists: true}}]}}],
    cursor: {}
});
```

**2。查找活动时间超过 30 分钟的光标**

```
// To find cursor which is running more than 30 mins
db.adminCommand({
    "currentOp": true,
    "active": true,
    "$all": true
}).inprog.filter(function(op) {
    return op.desc == "Cursor" && 
           op.secs_running > 1800 && 
           op.active == true;
}).sort((a, b) => b.microsecs_running - a.microsecs_running)
```

**3。通过监控垃圾收集器的进度 CloudWatch**

`LongestRunningGCProcess`— 最长活动垃圾收集过程的持续时间（以秒为单位）。每分钟更新一次，仅跟踪活动操作，不包括在一分钟时段内完成的进程。

`AvailableMVCCIds`-一个计数器，显示在达到零之前剩余的可用写入操作数。当此计数器达到零时，您的集群将进入只读模式，直至 ID 被回收并循环利用。计数器会在每次写入操作后递减，并在垃圾回收利用旧的 MVCC ID 后递增。

**注意**  
较低的 MVCC ID 和较长的垃圾收集持续时间并不完全归因于长时间运行的查询。 Write-intensive 资源受限的实例上的工作负载还可能导致 MVCC ID 可用性降低，垃圾收集周期延长。

## 补救策略
<a name="long-queries-remediation"></a>
+ 在应用程序中实现查询超时
+ 不要让光标存活时间更长
+ 优化查询以提高性能。
+ 更喜欢批量写入操作