

# Aurora PostgreSQL 查询计划管理的最佳实践
<a name="AuroraPostgreSQL.Optimize.BestPractice"></a>

使用查询计划管理功能，您可以控制更改查询执行计划的方式和时间。作为 DBA，使用 QPM 时的主要目标包括防止在数据库发生更改时性能下降，以及控制是否允许优化程序使用新计划。在下面，您可以找到一些使用查询计划管理的推荐最佳实践。主动式和反应式计划管理方法的不同之处在于如何以及何时批准使用新计划。

**Contents**
+ [主动式计划管理有助于防止性能下降](#AuroraPostgreSQL.Optimize.BestPractice.Proactive)
  + [确保主要版本升级后的计划稳定性](#AuroraPostgreSQL.Optimize.BestPractice.MajorVersionUpgrade)
+ [反应式计划管理可检测和修复性能下降](#AuroraPostgreSQL.Optimize.BestPractice.Reactive)

## 主动式计划管理有助于防止性能下降
<a name="AuroraPostgreSQL.Optimize.BestPractice.Proactive"></a>

为了防止出现计划性能倒退，您可以通过运行一个过程来*改进*计划基线，该过程将新发现的计划的性能与已批准计划的现有基线的性能进行比较，然后自动批准最快的一组计划作为新的基线。这样，随着发现更快的计划，计划的基线会随着时间推移而提高。

1. 在开发环境中，确定对性能或系统吞吐量造成最大影响的 SQL 语句。然后捕获这些语句中的计划，如[手动捕获特定 SQL 语句的计划](AuroraPostgreSQL.Optimize.CapturePlans.md#AuroraPostgreSQL.Optimize.CapturePlans.Manual)和[自动捕获计划](AuroraPostgreSQL.Optimize.CapturePlans.md#AuroraPostgreSQL.Optimize.CapturePlans.Automatic)中所述。

1. 将捕获的计划从开发环境导出并导入到生产环境中。有关更多信息，请参阅“[导出和导入 Aurora PostgreSQL 的托管式计划](AuroraPostgreSQL.Optimize.Maintenance.ExportingImporting.md)”。

1. 在生产环境中，运行您的应用程序并强制使用批准的托管计划。有关更多信息，请参阅“[使用 Aurora PostgreSQL 托管式计划](AuroraPostgreSQL.Optimize.UsePlans.md)”。在应用程序运行时，随着优化程序的发现还可添加新计划。有关更多信息，请参阅“[自动捕获计划](AuroraPostgreSQL.Optimize.CapturePlans.md#AuroraPostgreSQL.Optimize.CapturePlans.Automatic)”。

1. 分析未批准的计划并批准那些执行良好的计划。有关更多信息，请参阅“[评估计划性能](AuroraPostgreSQL.Optimize.Maintenance.md#AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance)”。

1. 在应用程序持续运行时，优化程序开始相应使用新计划。

### 确保主要版本升级后的计划稳定性
<a name="AuroraPostgreSQL.Optimize.BestPractice.MajorVersionUpgrade"></a>

PostgreSQL 的每个主要版本都包括对查询优化程序的增强和更改，旨在提高性能。但是，优化器在早期版本中生成的查询执行计划可能会导致较新的升级版本性能下降。在主要版本升级后，您可以使用查询计划管理来解决这些性能问题并确保计划的稳定性。

即使同一个语句存在多个批准计划，优化器也始终使用成本最低的批准计划。升级后，优化器可能会发现新的计划，但它们将被保存为未批准的计划。这些计划只有在使用反应式计划管理和 unapproved\$1plan\$1execution\$1threshold 参数获得批准后才会执行。您可以使用反应式计划管理和 evolve\$1plan\$1baselines 参数来最大限度地提高计划的稳定性。这将新计划的绩效与旧计划的绩效进行比较，然后批准或拒绝比次优计划至少快 10％ 的计划。

升级后，您可以使用 `evolve_plan_baselines` 函数来比较使用查询参数绑定进行升级前后的计划性能。以下步骤假定您一直在生产环境中使用经批准的托管计划，详情请参阅 [使用 Aurora PostgreSQL 托管式计划](AuroraPostgreSQL.Optimize.UsePlans.md)。

1. 升级前，请在运行查询计划管理器的情况下运行应用程序。当应用程序运行时，在优化程序发现新计划时添加它们。有关更多信息，请参阅 [自动捕获计划](AuroraPostgreSQL.Optimize.CapturePlans.md#AuroraPostgreSQL.Optimize.CapturePlans.Automatic)。

1. 评估每个计划的性能。有关更多信息，请参阅 [评估计划性能](AuroraPostgreSQL.Optimize.Maintenance.md#AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance)。

1. 升级后，请再次使用 `evolve_plan_baselines` 函数分析经批准的计划。比较使用查询参数绑定前后的性能。如果新计划较快，您可以将其添加到经批准的计划中。如果它比相同参数绑定的另一个计划更快，那么您可以将较慢的计划标记为“已被拒绝”。

   有关更多信息，请参阅 [批准更好的计划](AuroraPostgreSQL.Optimize.Maintenance.md#AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance.Approving)。有关此函数的参考信息，请参阅[apg\$1plan\$1mgmt.evolve\$1plan\$1baselines](AuroraPostgreSQL.Optimize.Functions.md#AuroraPostgreSQL.Optimize.Functions.evolve_plan_baselines)。

有关更多信息，请参阅[使用 Amazon Aurora PostgreSQL 兼容版查询计划管理确保主要版本升级后性能一致](https://aws.amazon.com/blogs/database/ensuring-consistent-performance-after-major-version-upgrades-with-amazon-aurora-postgresql-query-plan-management/)。

**注意**  
使用逻辑复制或 AWS DMS 执行主要版本升级时，请确保复制 `apg_plan_mgmt` 模式，以确保将现有计划复制到升级后的实例。有关逻辑复制的更多信息，请参阅 [使用逻辑复制对 Aurora PostgreSQL 执行主要版本升级](AuroraPostgreSQL.MajorVersionUpgrade.md)。

## 反应式计划管理可检测和修复性能下降
<a name="AuroraPostgreSQL.Optimize.BestPractice.Reactive"></a>

通过在应用程序运行时进行监控，您可以检测造成性能下降的计划。检测到性能下降时，您可以按照以下步骤手动拒绝或修复糟糕的计划：

1. 在应用程序运行时，强制使用托管计划并自动添加新发现的计划作为未批准的计划。有关更多信息，请参阅“[使用 Aurora PostgreSQL 托管式计划](AuroraPostgreSQL.Optimize.UsePlans.md)”和“[自动捕获计划](AuroraPostgreSQL.Optimize.CapturePlans.md#AuroraPostgreSQL.Optimize.CapturePlans.Automatic)”。

1. 监控正在运行应用程序的性能下降。

1. 在您发现计划性能下降时，请将计划的状态设置为 `rejected`。下次优化程序运行 SQL 语句时，它会自动忽略拒绝的计划，并改为使用不同的已批准计划。有关更多信息，请参阅“[拒绝或禁用速度较慢的计划](AuroraPostgreSQL.Optimize.Maintenance.md#AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance.Rejecting)”。

   在某些情况下，您可能会偏好修复糟糕的计划而不是拒绝、禁用或删除该计划。使用 `pg_hint_plan` 扩展来试验改进计划。通过 `pg_hint_plan`，您使用特殊注释告知优化程序覆盖其通常创建计划的方式。有关更多信息，请参阅 [使用 pg\$1hint\$1plan 修复计划](AuroraPostgreSQL.Optimize.Maintenance.md#AuroraPostgreSQL.Optimize.Maintenance.pg_hint_plan)。