

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 改善 Aurora PostgreSQL 查詢計劃
<a name="AuroraPostgreSQL.Optimize.Maintenance"></a>

透過評估計劃效能和修正計劃來改善查詢計劃管理。如需改善查詢計劃的詳細資訊，請參閱下列主題。

**Topics**
+ [評估計劃效能](#AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance)
+ [使用 pg\$1hint\$1plan 修正計劃](#AuroraPostgreSQL.Optimize.Maintenance.pg_hint_plan)

## 評估計劃效能
<a name="AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance"></a>

當最佳化工具將計劃擷取為未核准之後，請使用 `apg_plan_mgmt.evolve_plan_baselines` 函數，根據實際效能來比較計劃。根據效能試驗的結果而定，您可以將計劃的狀態從未核准變更為已核准或已拒絕。如果計劃不符合您的需要，您可以改為決定使用 `apg_plan_mgmt.evolve_plan_baselines` 函數來暫時停用計劃。

### 核准較佳計劃
<a name="AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance.Approving"></a>

以下範例示範如何使用 `apg_plan_mgmt.evolve_plan_baselines` 函數，將受管計劃的狀態變更為已核准。

```
SELECT apg_plan_mgmt.evolve_plan_baselines (
   sql_hash, 
   plan_hash, 
   min_speedup_factor := 1.0, 
   action := 'approve'
) 
FROM apg_plan_mgmt.dba_plans WHERE status = 'Unapproved';
```

```
NOTICE:     rangequery (1,10000)
NOTICE:     Baseline   [ Planning time 0.761 ms, Execution time 13.261 ms]
NOTICE:     Baseline+1 [ Planning time 0.204 ms, Execution time 8.956 ms]
NOTICE:     Total time benefit: 4.862 ms, Execution time benefit: 4.305 ms
NOTICE:     Unapproved -> Approved
evolve_plan_baselines 
-----------------------
0
(1 row)
```

輸出顯示 `rangequery` 陳述式的效能報告，參數繫結為 1 和 10,000。新的未核准計劃 (`Baseline+1`) 比先前已核准的最佳計劃 (`Baseline`) 更好。若要確認新計劃現在 `Approved`，請查看 `apg_plan_mgmt.dba_plans` 檢視。

```
SELECT sql_hash, plan_hash, status, enabled, stmt_name 
FROM apg_plan_mgmt.dba_plans;
```

```
sql_hash  | plan_hash |  status  | enabled | stmt_name  
------------+-----------+----------+---------+------------
1984047223 | 512153379 | Approved | t       | rangequery
1984047223 | 512284451 | Approved | t       | rangequery
(2 rows)
```

受管計劃現在包含兩個已核准的計劃，當作陳述式的計劃基線。您也可以呼叫 `apg_plan_mgmt.set_plan_status` 函數，直接將計劃的狀態欄位設為 `'Approved'`、`'Rejected'`、`'Unapproved'` 或 `'Preferred'`。

### 拒絕或停用較慢的計劃
<a name="AuroraPostgreSQL.Optimize.Maintenance.EvaluatingPerformance.Rejecting"></a>

若要拒絕或停用計劃，請將 `'reject'` 或 `'disable' `當作動作參數傳給 `apg_plan_mgmt.evolve_plan_baselines` 函數。此範例停用任何已擷取的 `Unapproved` 計劃，該計劃比陳述式的最佳 `Approved` 計劃還慢至少 10%。

```
SELECT apg_plan_mgmt.evolve_plan_baselines(
sql_hash,  -- The managed statement ID
plan_hash, -- The plan ID
1.1,       -- number of times faster the plan must be 
'disable'  -- The action to take. This sets the enabled field to false.
)
FROM apg_plan_mgmt.dba_plans
WHERE status = 'Unapproved' AND   -- plan is Unapproved
origin = 'Automatic';       -- plan was auto-captured
```

您也可以直接將計劃設為已拒絕或已停用。若要直接將計劃的已啟用欄位設為 `true` 或 `false`，請呼叫 `apg_plan_mgmt.set_plan_enabled` 函數。若要直接將計劃的狀態欄位設為 `'Approved'`、`'Rejected'`、`'Unapproved'` 或 `'Preferred'`，請呼叫 `apg_plan_mgmt.set_plan_status` 函數。

若要刪除無效和您預期仍無效的計劃，請使用 `apg_plan_mgmt.validate_plans` 函數。此函數可讓您刪除或停用無效的計劃。如需詳細資訊，請參閱[驗證計劃](AuroraPostgreSQL.Optimize.Deleting.md#AuroraPostgreSQL.Optimize.Maintenance.ValidatingPlans)。

## 使用 pg\$1hint\$1plan 修正計劃
<a name="AuroraPostgreSQL.Optimize.Maintenance.pg_hint_plan"></a>

查詢最佳化工具精心設計來為所有陳述式尋找最佳計劃，且最佳化工具在大多數情況下會找到好的計劃。不過，有時您可能知道有一個比最佳化工具所產生的計劃好得多的計劃。有兩個建議方法可讓最佳化工具產生理想的計劃，包括使用 `pg_hint_plan` 延伸，或在 PostgreSQL 中設定 Grand Unified Configuration (GUC) 變數：
+ `pg_hint_plan` 延伸 – 使用 PostgreSQL 的 `pg_hint_plan` 延伸來指定「提示」，以修改規劃器的運作方式。若要安裝和進一步了解如何使用 `pg_hint_plan` 延伸，請參閱 [pg\$1hint\$1plan 文件](https://github.com/ossc-db/pg_hint_plan)。
+ GUC 變數 – 覆寫一個或多個成本模型參數或其他最佳化工具參數，例如 `from_collapse_limit` 或 `GEQO_threshold`。

當您使用以上其中一項技巧來強制查詢最佳化工具使用計劃時，您也可以使用查詢計劃管理來擷取和強制使用新的計劃。

您可以使用 `pg_hint_plan` 延伸來變更 SQL 陳述式的聯結順序、聯結方法或存取路徑。您使用 SQL 註解搭配特殊的 `pg_hint_plan` 語法，以修改最佳化工具建立計劃的方式。例如，假設有問題的 SQL 陳述式具有雙向聯結。

```
SELECT * 
FROM t1, t2 
WHERE t1.id = t2.id;
```

再假設最佳化工具選擇聯結順序 (t1, t2)，但您知道聯結順序 (t2, t1) 更快。下列提示強制最佳化工具使用較快的聯結順序 (t2, t1)。包含 EXPLAIN 會讓最佳化工具為 SQL 陳述式產生計劃，但不需執行陳述式。(未顯示輸出。)

```
/*+ Leading ((t2 t1)) */ EXPLAIN SELECT * 
FROM t1, t2 
WHERE t1.id = t2.id;
```

下列步驟示範如何使用 `pg_hint_plan`。

**使用 pg\$1hint\$1plan 修改最佳化工具所產生的計劃並擷取計劃**

1. 啟用手動擷取模式。

   ```
   SET apg_plan_mgmt.capture_plan_baselines = manual;
   ```

1. 針對所關注的 SQL 陳述式來指定提示。

   ```
   /*+ Leading ((t2 t1)) */ EXPLAIN SELECT * 
   FROM t1, t2 
   WHERE t1.id = t2.id;
   ```

   執行之後，最佳化工具會擷取 `apg_plan_mgmt.dba_plans` 檢視中的計劃。擷取的計劃不含特殊的 `pg_hint_plan` 註解語法，因為查詢計劃管理會移除開頭註解而將陳述式標準化。

1. 使用 `apg_plan_mgmt.dba_plans` 檢視來檢視受管計劃。

   ```
   SELECT sql_hash, plan_hash, status, sql_text, plan_outline 
   FROM apg_plan_mgmt.dba_plans;
   ```

1. 將計劃的狀態設定為 `Preferred`。當最低成本的計劃還不是 `Approved` 或 `Preferred` 時，這麼做可以保證最佳化工具選擇執行該計劃，而非從已核准的一組計劃中選擇。

   ```
   SELECT apg_plan_mgmt.set_plan_status(sql-hash, plan-hash, 'preferred' ); 
   ```

1. 關閉手動計劃擷取並強制使用受管計劃。

   ```
   SET apg_plan_mgmt.capture_plan_baselines = false;
   SET apg_plan_mgmt.use_plan_baselines = true;
   ```

   現在，當原始 SQL 陳述式執行時，最佳化工具會選擇 `Approved` 或 `Preferred` 計劃。如果最低成本計劃不是 `Approved` 也不是 `Preferred`，最佳化工具會選擇 `Preferred` 計劃。