

# 优化 Aurora PostgreSQL 中的查询性能
<a name="AuroraPostgreSQL.optimizing.queries"></a>

优化查询性能至关重要，因为这有助于数据库更快、更高效地运行，同时使用更少的资源，从而改善用户体验并降低运营成本。Amazon Aurora PostgreSQL 提供了多项功能来协助优化 PostgreSQL 工作负载的查询性能。

**Topics**
+ [使用 Aurora 优化型读取功能提高 Aurora PostgreSQL 的查询性能](AuroraPostgreSQL.optimized.reads.md)
+ [优化 Aurora PostgreSQL 中的关联子查询](apg-correlated-subquery.md)
+ [使用自适应联接提高查询性能](user-apg-adaptive-join.md)
+ [使用共享计划缓存](apg-shared-plan-cache.md)

# 使用 Aurora 优化型读取功能提高 Aurora PostgreSQL 的查询性能
<a name="AuroraPostgreSQL.optimized.reads"></a>

使用 Aurora 优化型读取功能，您可以实现更快的 Aurora PostgreSQL 查询处理。使用 Aurora 优化型读取功能的 Aurora PostgreSQL 数据库实例可将查询延迟缩短多达 8 倍，对于具有超出数据库实例内存容量的大型数据集的应用程序，最多可节省 30% 的成本。

**Topics**
+ [PostgreSQL 中的 Aurora 优化型读取功能概述](#AuroraPostgreSQL.optimized.reads.overview)
+ [使用 Aurora 优化型读取](#AuroraPostgreSQL.optimized.reads.using)
+ [Aurora 优化型读取的使用案例](#AuroraPostgreSQL.optimized.reads.usecases)
+ [监控使用 Aurora 优化读取的数据库实例](#AuroraPostgreSQL.optimized.reads.monitoring)
+ [Aurora 优化型读取的最佳实践](#AuroraPostgreSQL.optimized.reads.bestpractices)

## PostgreSQL 中的 Aurora 优化型读取功能概述
<a name="AuroraPostgreSQL.optimized.reads.overview"></a>

创建使用基于 Graviton 的 R6gd、R8gd 和基于英特尔的 R6id 实例以及非易失性存储规范（NVMe）存储的数据库集群时，默认可以使用 Aurora 优化型读取功能。可在以下 PostgreSQL 版本中可使用此功能：
+ 对于 R8gd 实例，为 14.12 及更高版本、15.7 及更高版本、16.3 及更高版本、17.4 及更高版本
+ 对于 R6gd 和 R6id 实例，为 14.9 及更高版本、15.4 及更高版本、16.1 及所有更高版本

Aurora 优化型读取支持两种功能：分层缓存和临时对象。

**启用优化型读取的分层缓存** - 使用分层缓存，您可以将数据库实例缓存容量最多扩展至实例内存的 5 倍。这样可以自动维护缓存以包含最新的、事务一致的数据，从而使应用程序免除管理基于外部结果集的缓存解决方案数据货币的开销。对于之前从 Aurora 存储中获取数据的查询，查询延迟可缩短高达 8 倍。

在 Aurora 中，默认参数组中 `shared_buffers` 的值通常设置为可用内存的 75% 左右。但是，对于 r8gd、r6gd 和 r6id 实例类型，Aurora 将减少 4.5% 的 `shared_buffers` 空间，用于托管优化型读取缓存的元数据。

**启用优化型读取的临时对象** - 使用临时对象，您可以通过将 PostgreSQL 生成的临时文件放置在本地 NVMe 存储上来实现更快的查询处理。这将减少通过网络流向 Elastic Block Storage（EBS）的流量。对于排序、联接或合并大量数据而不符合数据库实例上可用内存容量范围的高级查询，延迟可缩短高达 2 倍，吞吐量可提升高达 2 倍。

在 Aurora I/O 优化版集群上，优化型读取同时在 NVMe 存储上利用分层缓存和临时对象。借助启用了优化型读取的分层缓存功能，Aurora 为临时对象分配 2 倍的实例内存，为内部操作分配大约 10% 的存储，剩余的存储作为分层缓存。在 Aurora 标准集群上，优化型读取仅使用临时对象。

Aurora I/O 优化型集群可让您在实例级别使用动态参数 `aurora_temp_space_size`，来调整已启用优化型读取功能的临时对象的分配空间大小。可以在以下 PostgreSQL 版本中使用此调整大小功能：
+ 16.8 及所有更高版本
+ 15.12 及更高的 15 版本
+ 14.17 及更高的 14 版本

使用此参数，无需重新启动数据库引擎，即可调整实例内存的容量（范围从 2 倍到最多 6 倍）。当您扩展临时对象空间时，无论并发工作负载如何，更改都会立即生效。但是，当您缩小空间时，只有当临时对象中有足够的未使用空间来容纳新的大小请求之后，调整才会完成。调整启用了优化型读取功能的临时对象的大小后，分层缓存会自动调整以使用任何可用空间。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.optimized.reads.html)

**注意**  
在基于 NVMe 的数据库实例类上，在 IO 优化型集群和标准集群之间切换会导致数据库引擎立即重启。

在 Aurora PostgreSQL 中，使用 `temp_tablespaces` 参数配置存储临时对象的表空间。

要检查是否配置了临时对象，请使用以下命令：

```
postgres=> show temp_tablespaces;
temp_tablespaces
---------------------
aurora_temp_tablespace
(1 row)
```

`aurora_temp_tablespace` 是由 Aurora 配置的指向 NVMe 本地存储的表空间。您无法修改此参数或切换回 Amazon EBS 存储。

要检查优化型读取缓存是否已开启，请使用以下命令：

```
postgres=> show shared_preload_libraries;
                 shared_preload_libraries
--------------------------------------------------------
rdsutils,pg_stat_statements,aurora_optimized_reads_cache
```

## 使用 Aurora 优化型读取
<a name="AuroraPostgreSQL.optimized.reads.using"></a>

当使用其中一个基于 NVMe 的数据库实例预调配 Aurora PostgreSQL 数据库实例时，该数据库实例会自动使用 Aurora 优化型读取功能。

要启用 Aurora 优化读取，请执行以下操作之一：
+ 使用其中一个基于 NVMe 的数据库实例类创建 Aurora PostgreSQL 数据库集群。有关更多信息，请参阅 [创建 Amazon Aurora 数据库集群](Aurora.CreateInstance.md)。
+ 修改现有 Aurora PostgreSQL 数据库集群，以使用其中一个基于 NVMe 的数据库实例类。有关更多信息，请参阅 [修改 Amazon Aurora 数据库集群](Aurora.Modifying.md)。

在支持其中一个或多个数据库实例类（具有本地 NVMe SSD 存储）的所有 AWS 区域中，均可使用 Aurora 优化型读取功能。有关更多信息，请参阅 [Amazon Aurora数据库实例类](Concepts.DBInstanceClass.md)。

要切换回未优化读取功能的 Aurora 实例，请将 Aurora 实例的数据库实例类修改为类似的实例类，该实例类对于数据库工作负载没有 NVMe 临时存储。例如，如果当前数据库实例类是 db.r6gd.4xlarge，请选择 db.r6g.4xlarge 以切换回该实例类。有关更多信息，请参阅[修改 Aurora 数据库实例](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html)。

## Aurora 优化型读取的使用案例
<a name="AuroraPostgreSQL.optimized.reads.usecases"></a>

**启用优化型读取的分层缓存**

以下是一些可从优化型读取分层缓存中受益的使用案例：
+ Internet 规模的应用程序，例如支付处理、计费、电子商务（具有严格的性能 SLA）。
+ 实时报告仪表板，可对指标/数据收集运行数百次单点查询。
+ 带有 pgvector 扩展的生成式人工智能应用程序，可在数百万个向量嵌入中搜索精确或最近的邻居。

**启用优化型读取的临时对象**

以下是一些可从优化型读取临时对象中受益的使用案例：
+ 包含公用表表达式（CTE）、派生表和分组操作的分析查询。
+ 用于处理应用程序的未优化型查询的只读副本。
+ 具有复杂操作（如 GROUP BY 和 ORDER BY）的按需或动态报告查询，这些操作无法始终使用适当的索引。
+ 用于排序的 `CREATE INDEX` 或 `REINDEX` 操作。
+ 使用内部临时表的其他工作负载。

## 监控使用 Aurora 优化读取的数据库实例
<a name="AuroraPostgreSQL.optimized.reads.monitoring"></a>

您可以使用 EXPLAIN 命令监控使用启用了优化型读取的分层缓存的查询，如以下示例所示：

```
Postgres=> EXPLAIN (ANALYZE, BUFFERS) SELECT c FROM sbtest15 WHERE id=100000000                   

QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using sbtest15_pkey on sbtest15  (cost=0.57..8.59 rows=1 width=121) (actual time=0.287..0.288 rows=1 loops=1)
   Index Cond: (id = 100000000)
   Buffers: shared hit=3 read=2 aurora_orcache_hit=2
   I/O Timings: shared/local read=0.264
 Planning:
   Buffers: shared hit=33 read=6 aurora_orcache_hit=6
   I/O Timings: shared/local read=0.607
 Planning Time: 0.929 ms
 Execution Time: 0.303 ms
(9 rows)
Time: 2.028 ms
```

**注意**  
只有在优化型读取功能处于开启状态，并且解释计划的 `Buffers` 部分中 `aurora_orcache_hit` 和 `aurora_storage_read` 字段的值大于零时，才会显示这些字段。读取字段是 `aurora_orcache_hit` 和 `aurora_storage_read` 字段的总和。

您可以通过以下 CloudWatch 指标监控使用 Aurora 优化型读取功能的数据库实例：
+ `AuroraOptimizedReadsCacheHitRatio`
+ `FreeEphemeralStorage`
+ `ReadIOPSEphemeralStorage`
+ `ReadLatencyEphemeralStorage`
+ `ReadThroughputEphemeralStorage`
+ `WriteIOPSEphemeralStorage`
+ `WriteLatencyEphemeralStorage`
+ `WriteThroughputEphemeralStorage`

这些指标提供有关可用实例存储的存储空间、IOPS 和吞吐量的数据。有关这些指标的更多信息，请参阅。[Amazon Aurora 的实例级指标](Aurora.AuroraMonitoring.Metrics.md#Aurora.AuroraMySQL.Monitoring.Metrics.instances)

您还可以使用此 `pg_proctab` 扩展来监控 NVMe 存储。

```
postgres=>select * from pg_diskusage();

major | minor |       devname       | reads_completed | reads_merged | sectors_read | readtime | writes_completed | writes_merged | sectors_written | writetime | current_io | iotime  | totaliotime
------+-------+---------------------+-----------------+--------------+--------------+----------+------------------+---------------+-----------------+-----------+------------+---------+-------------
      |       | rdstemp             |           23264 |            0 |       191450 |    11670 |          1750892 |             0 |        24540576 |    819350 |          0 | 3847580 |      831020
      |       | rdsephemeralstorage |           23271 |            0 |       193098 |     2620 |           114961 |             0 |        13845120 |    130770 |          0 |  215010 |      133410
(2 rows)
```

## Aurora 优化型读取的最佳实践
<a name="AuroraPostgreSQL.optimized.reads.bestpractices"></a>

对于 Aurora 优化型读取使用以下最佳实践：
+ 使用 CloudWatch 指标 `FreeEphemeralStorage` 监控实例存储上的可用存储空间。如果由于数据库实例上的工作负载导致实例存储达到其限制，请调整并发性和大量使用临时对象的查询，或者将其修改为使用更大的数据库实例类。
+ 监控 CloudWatch 指标的优化型读取缓存命中率。诸如 VACUUM 之类的操作可以非常快速地修改大量块。这可能会导致命中率暂时下降。`pg_prewarm` 扩展可用于将数据加载到缓冲区缓存中，从而允许 Aurora 主动将其中一些块写入优化型读取缓存。
+ 您可以启用集群缓存管理（CCM），在将用作故障转移目标的 Tier-0 读取器上预热缓冲区缓存和分层缓存。启用 CCM 后，会定期扫描缓冲区缓存，以便在分层缓存中写入符合驱逐条件的页面。有关 CCM 的更多信息，请参阅 [通过 Aurora PostgreSQL 的集群缓存管理提供故障转移后的快速恢复](AuroraPostgreSQL.cluster-cache-mgmt.md)。

# 优化 Aurora PostgreSQL 中的关联子查询
<a name="apg-correlated-subquery"></a>

 关联子查询引用外部查询中的表列。对于外部查询返回的每一行，关联子查询都会被评估一次。在以下示例中，子查询引用表 ot 中的一列。此表未包含在子查询的 FROM 子句中，但在外部查询的 FROM 子句中引用了该表。如果表 ot 有 100 万行，则需要对子查询评估 100 万次。

```
SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);
```

**注意**  
从版本 16.8 开始，Aurora PostgreSQL 中提供了子查询转换和子查询缓存，而适用于 Aurora PostgreSQL 的 Babelfish 从 4.2.0 开始支持这些功能。
从适用于 Aurora PostgreSQL 的 Babelfish 版本 4.6.0 和 5.2.0 开始，以下参数控制这些功能：  
 babelfishpg\$1tsql.apg\$1enable\$1correlated\$1scalar\$1transform 
 babelfishpg\$1tsql.apg\$1enable\$1subquery\$1cache 
默认情况下，这两个参数均处于开启状态。

## 使用子查询转换提高 Aurora PostgreSQL 查询性能
<a name="apg-corsubquery-transformation"></a>

Aurora PostgreSQL 可以通过将关联子查询转换为等效的外部联接来加速这些子查询。此优化适用于以下两种类型的关联子查询：
+ 返回单个聚合值并出现在 SELECT 列表中的子查询。

  ```
  SELECT ot.a, ot.b, (SELECT AVG(it.b) FROM it WHERE it.a = ot.a) FROM ot;
  ```
+ 返回单个聚合值并出现在 WHERE 子句中的子查询。

  ```
  SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);
  ```

### 在子查询中启用转换
<a name="apg-corsub-transform"></a>

 要支持将关联子查询转换为等效的外部联接，请将 `apg_enable_correlated_scalar_transform` 参数设置为 `ON`。此参数的默认值为 `OFF`。

您可以修改集群或实例参数组来设置参数。要了解更多信息，请参阅[Amazon Aurora 的参数组](USER_WorkingWithParamGroups.md)。

或者，可以通过以下命令来仅为当前会话配置此设置：

```
SET apg_enable_correlated_scalar_transform TO ON;
```

### 验证转换
<a name="apg-corsub-transform-confirm"></a>

使用 EXPLAIN 命令来验证关联子查询是否已在查询计划中转换为外部联接。

 启用转换后，适用的关联子查询部分将转换为外部联接。例如：

```
postgres=> CREATE TABLE ot (a INT, b INT);
CREATE TABLE
postgres=> CREATE TABLE it (a INT, b INT);
CREATE TABLE

postgres=> SET apg_enable_correlated_scalar_transform TO ON;
SET
postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);

                         QUERY PLAN
--------------------------------------------------------------
 Hash Join
   Hash Cond: (ot.a = apg_scalar_subquery.scalar_output)
   Join Filter: ((ot.b)::numeric < apg_scalar_subquery.avg)
   ->  Seq Scan on ot
   ->  Hash
         ->  Subquery Scan on apg_scalar_subquery
               ->  HashAggregate
                     Group Key: it.a
                     ->  Seq Scan on it
```

将 GUC 参数设置为 `OFF` 时，不会转换相同的查询。计划将不会有外部联接，而是有子计划。

```
postgres=> SET apg_enable_correlated_scalar_transform TO OFF;
SET
postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);
                QUERY PLAN
----------------------------------------
 Seq Scan on ot
   Filter: ((b)::numeric < (SubPlan 1))
   SubPlan 1
     ->  Aggregate
           ->  Seq Scan on it
                 Filter: (a = ot.a)
```

### 限制
<a name="apg-corsub-transform-limitations"></a>
+ 子查询必须位于 SELECT 列表中或 where 子句的其中一个条件中。否则，不会转换此子查询。
+ 子查询必须返回一个聚合函数。不支持用户定义的聚合函数进行转换。
+ 返回表达式不是简单聚合函数的子查询不会被转换。
+ 子查询 WHERE 子句中的关联条件应该是简单的列引用。否则，不会转换此子查询。
+ 子查询中的关联条件，其中子句必须是普通的相等谓词。
+ 子查询不能包含 HAVING 或 GROUP BY 子句。
+ 子查询中的 where 子句可能包含一个或多个使用 AND 组合的谓词。

**注意**  
转换对性能的影响因您的架构、数据和工作负载而异。随着外部查询生成的行数的增加，将子查询执行与转换关联可以显著提高性能。我们强烈建议您先在非生产环境中使用实际架构、数据和工作负载测试此功能，然后才在生产环境中启用。

## 使用子查询缓存提高 Aurora PostgreSQL 查询性能
<a name="apg-subquery-cache"></a>

 Aurora PostgreSQL 支持子查询缓存来存储关联子查询的结果。当子查询结果已经在缓存中时，此功能会跳过重复的关联子查询执行。

### 了解子查询缓存
<a name="apg-subquery-cache-understand"></a>

 PostgreSQL 的 Memoize 节点是子查询缓存的关键部分。Memoize 节点在本地缓存中维护一个哈希表，用于从输入参数值映射到查询结果行。哈希表的内存限制是 work\$1mem 和 hash\$1mem\$1multiplier 的乘积。要了解更多信息，请参阅 [Resource Consumption](https://www.postgresql.org/docs/16/runtime-config-resource.html)。

 在查询执行期间，子查询缓存使用缓存命中率（CHR）来估计缓存是否提高了查询性能，并在查询运行时决定是否继续使用缓存。CHR 是缓存命中数与请求总数的比率。例如，如果关联子查询需要执行 100 次，并且可以从缓存中检索 70 个执行结果，则 CHR 为 0.7。

对于每个 apg\$1subquery\$1cache\$1check\$1interval 缓存未命中次数，可通过检查 CHR 是否大于 apg\$1subquery\$1cache\$1hit\$1rate\$1threshold 来评估子查询缓存的好处。否则，将从内存中删除缓存，查询执行将返回到原始、未缓存的子查询重新执行状态。

### 控制子查询缓存行为的参数
<a name="apg-subquery-cache-parameters"></a>

下表列出了控制子查询缓存行为的参数。


|  参数  | 说明  | 默认值 | 已允许  | 
| --- | --- | --- | --- | 
| apg\$1enable\$1subquery\$1cache  | 支持对关联标量子查询使用缓存。  | 关闭  | ON、OFF | 
| apg\$1subquery\$1cache\$1check\$1interval  | 设置评估子查询缓存命中率的频率（以缓存未命中次数为单位）。  | 500  | 0–2147483647 | 
| apg\$1subquery\$1cache\$1hit\$1rate\$1threshold  | 设置子查询缓存命中率的阈值。  | 0.3  | 0.0–1.0 | 

**注意**  
较大的 `apg_subquery_cache_check_interval` 值可能会提高基于 CHR 的缓存优势估计的准确性，但会增加缓存开销，因为在缓存表具有 `apg_subquery_cache_check_interval` 行之前不会对 CHR 进行评估。
较大的 `apg_subquery_cache_hit_rate_threshold` 值偏向于放弃子查询缓存，而返回到原始、未缓存子查询重新执行状态。

您可以修改集群或实例参数组来设置参数。要了解更多信息，请参阅[Amazon Aurora 的参数组](USER_WorkingWithParamGroups.md)。

或者，可以通过以下命令来仅为当前会话配置此设置：

```
SET apg_enable_subquery_cache TO ON;
```

### 在 Aurora PostgreSQL 中开启子查询缓存
<a name="apg-subquery-cache-turningon"></a>

启用子查询缓存后，Aurora PostgreSQL 会应用缓存来保存子查询结果。然后，查询计划将在 SubPlan 下有一个 Memoize 节点。

 例如，以下命令序列显示了没有子查询缓存的简单关联子查询的估计查询执行计划。

```
postgres=> SET apg_enable_subquery_cache TO OFF;
SET
postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a);

             QUERY PLAN
------------------------------------
 Seq Scan on ot
   Filter: (b < (SubPlan 1))
   SubPlan 1
     ->  Seq Scan on it
           Filter: (a = ot.a)
```

开启 `apg_enable_subquery_cache` 后，查询计划将在 SubPlan 节点下包含一个 Memoize 节点，表示子查询正计划使用缓存。

```
postgres=> SET apg_enable_subquery_cache TO ON;
SET
postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a);

             QUERY PLAN
------------------------------------
 Seq Scan on ot
   Filter: (b < (SubPlan 1))
   SubPlan 1
     ->  Memoize
           Cache Key: ot.a
           Cache Mode: binary
           ->  Seq Scan on it
                 Filter: (a = ot.a)
```

 实际的查询执行计划包含子查询缓存的更多详细信息，包括缓存命中和缓存未命中。以下输出显示了在向表中插入一些值后，上述示例查询的实际查询执行计划。

```
postgres=> EXPLAIN (COSTS FALSE, TIMING FALSE, ANALYZE TRUE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a);
            QUERY PLAN
-----------------------------------------------------------------------------
 Seq Scan on ot (actual rows=2 loops=1)
   Filter: (b < (SubPlan 1))
   Rows Removed by Filter: 8
   SubPlan 1
     ->  Memoize (actual rows=0 loops=10)
           Cache Key: ot.a
           Cache Mode: binary
           Hits: 4  Misses: 6  Evictions: 0  Overflows: 0  Memory Usage: 1kB
           ->  Seq Scan on it (actual rows=0 loops=6)
                 Filter: (a = ot.a)
                 Rows Removed by Filter: 4
```

缓存命中总数为 4，缓存未命中总数为 6。如果命中和未命中总数小于 Memoize 节点中的循环次数，则意味着 CHR 评估未通过，缓存已在某个时候被清理并放弃。然后，子查询执行返回到原始未缓存的重新执行状态。

### 限制
<a name="apg-subquery-cache-limitations"></a>

子查询缓存不支持关联子查询的某些规律。这些类型的查询将在没有缓存的情况下运行，即使子查询缓存已开启也是如此：
+ IN/EXISTS/ANY/ALL 关联子查询
+ 包含非确定性函数的关联子查询。
+ 关联子查询，它们引用其数据类型不支持哈希或相等操作的外部表列。

# 使用自适应联接提高查询性能
<a name="user-apg-adaptive-join"></a>

## 概述
<a name="user-apg-adaptive-join-intro"></a>

自适应联接是 Aurora PostgreSQL 17.4 中的一项预览功能，有助于提高查询性能。默认情况下，此功能处于禁用状态，但您可以使用全局用户配置（GUC）参数将其启用。由于这是一项预览功能，因此默认参数值可能会发生变化。启用后，自适应联接通过在运行时从嵌套循环联接动态切换到哈希联接，有助于优化查询性能。当 PostgreSQL 优化器由于基数估计值不准确而错误地选择了嵌套循环连接时，就会发生这种切换。

## 配置自适应联接
<a name="user-apg-adaptive-join-config"></a>

可以使用以下三个 GUC 参数控制自适应联接：


**自适应联接配置参数**  

| GUC 参数 | 说明 | 默认值和配置选项 | 
| --- | --- | --- | 
| apg\$1adaptive\$1join\$1crossover\$1multiplier | 此乘数与行交叉点结合使用，以确定何时从嵌套循环切换到哈希联接。行交叉点是 SQL 优化器估计嵌套循环和哈希联接操作具有相等成本的地方。较高的乘数值会降低自适应联接切换到哈希连接的可能性。 |  控制是否启用自适应联接 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/user-apg-adaptive-join.html)  | 
| apg\$1adaptive\$1join\$1cost\$1threshold | 此参数设置最低查询成本阈值。对于低于此阈值的查询，自适应联接会自动禁用。这样可以防止简单查询中的性能开销，在这种查询中，规划自适应联接的成本可能会超过从嵌套循环切换到哈希联接的优势。 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/user-apg-adaptive-join.html)  | 
| apg\$1enable\$1parameterized\$1adaptive\$1join | 启用后，此参数将自适应联接功能扩展到参数化的嵌套循环联接。默认情况下，自适应联接仅适用于未参数化的嵌套循环联接，因为这些联接更有可能从切换到哈希联接而受益。参数化嵌套循环联接通常性能更好，而使得切换到哈希联接并不那么重要。 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/user-apg-adaptive-join.html) 要求先启用 `apg_adaptive_join_crossover_multiplier`  | 

# 使用共享计划缓存
<a name="apg-shared-plan-cache"></a>

## 概述
<a name="apg-shared-plan-cache-overview"></a>

Aurora PostgreSQL 使用 process-per-user（每用户进程）模式，在这种模式下，每个客户端连接都会创建一个专用的后端进程。每个后端进程都为预准备语句维护其自己的本地计划缓存。由于这些缓存无法在进程之间共享，因此，使用许多预准备语句的应用程序可能会在不同的后端进程之间创建重复的缓存，从而导致内存使用量增加。

Aurora PostgreSQL 版本 17.6 及更高版本和 16.10 及更高版本引入了共享计划缓存功能。启用此功能后，后端进程可以共享通用计划，从而通过消除重复的计划生成来减少内存使用量并提高性能。

共享计划缓存使用以下组件作为其缓存密钥：
+ 查询字符串（包括注释）
+ 与规划程序相关的 GUC 参数（包括 `search_path`）
+ 用户 ID
+ 数据库 ID

实例重启会重置共享缓存。

## 参数
<a name="apg-shared-plan-cache-parameters"></a>

下表介绍用于控制共享计划缓存功能的参数：


| 参数 | 说明 | 默认值 | 已允许 | 
| --- | --- | --- | --- | 
| apg\$1shared\$1plan\$1cache.enable | 开启或关闭共享计划缓存 | 0（关闭） | 0, 1 | 
| apg\$1shared\$1plan\$1cache.max | 最大缓存条目数量 | 200–1000（视实例大小而定） | 100–50000 | 
| apg\$1shared\$1plan\$1cache.min\$1size\$1per\$1entry | 要存储在共享缓存中的最小计划大小。较小的计划使用本地缓存来优化 OLTP 性能。 | 16 KB | 0–32768（KB） | 
| apg\$1shared\$1plan\$1cache.max\$1size\$1per\$1entry | 共享缓存的最大计划大小。更大的计划仅存储成本信息。 | 256 KB–4 MB（视实例大小而定） | 0–32768（KB） | 
| apg\$1shared\$1plan\$1cache.idle\$1generic\$1plan\$1release\$1timeout | 一个时间，空闲会话在该时间之后发布本地通用计划。值较低可以节省内存；值较高可能会提高性能。 | 10 秒 | 0–2147483647（毫秒） | 

**注意**  
无需重新启动即可修改所有参数。

## 监控视图和函数
<a name="apg-shared-plan-cache-monitoring"></a>
+ `apg_shared_plan_cache()`：显示详细的缓存条目信息（命中、有效性、时间戳）
+ `apg_shared_plan_cache_stat()`：显示实例级别的统计数据（驱逐、失效）
+ `apg_shared_plan_cache_reset()`：移除 `apg_shared_plan_cache()` 和 `apg_shared_plan_cache_stat()` 中的所有条目
+ `apg_shared_plan_cache_remove(cache_key)`：从条目与 `cache_key` 匹配的 `apg_shared_plan_cache()` 中移除该条目

## 限制
<a name="apg-shared-plan-cache-limitations"></a>
+ 仅适用于预准备语句，而不缓存 PL/pgSQL 语句
+ 不缓存包含临时表或目录表的查询
+ 不缓存依赖于 RLS（行级安全性）的查询
+ 每个副本都保持其自己的缓存（没有跨副本共享）