

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

# Aurora MySQL 中平行查詢的 SQL 建構
<a name="aurora-mysql-parallel-query-sql"></a>

 在下節中，您可以找到更多有關特定 SQL 陳述式為何使用或不使用平行查詢的詳細資訊。本節還會詳細說明 Aurora MySQL 功能與平行查詢互動的方式。這些詳細資訊可協助您診斷使用平行查詢之叢集的效能問題，或了解平行查詢如何適用於您的特定工作負載。

 使用平行查詢的決策依賴許多發生在陳述式執行時的因素。因此，平行查詢可能一律、從未或只在特定條件下用於特定查詢。

**提示**  
 當您以 HTML 檢視這些範例時，您可以使用每個程式碼清單右上角的 **Copy (複製)** 小工具，複製 SQL 程式碼來自行嘗試。使用 **Copy (複製)** 小工具可避免複製 `mysql>` 提示和 `->` 接續資料行周圍的額外字元。

**Topics**
+ [EXPLAIN 陳述式](#aurora-mysql-parallel-query-sql-explain)
+ [WHERE 子句](#aurora-mysql-parallel-query-sql-where)
+ [資料定義語言 (DDL)](#aurora-mysql-parallel-query-sql-ddl)
+ [資料欄資料類型](#aurora-mysql-parallel-query-sql-datatypes)
+ [分割的資料表](#aurora-mysql-parallel-query-sql-partitioning)
+ [彙整函數、GROUP BY 子句和 HAVING 子句](#aurora-mysql-parallel-query-sql-aggregation)
+ [WHERE 子句中的函數呼叫](#aurora-mysql-parallel-query-sql-functions)
+ [LIMIT 子句](#aurora-mysql-parallel-query-sql-limit)
+ [比較運算子](#aurora-mysql-parallel-query-sql-comparisons)
+ [聯結](#aurora-mysql-parallel-query-sql-joins)
+ [子查詢](#aurora-mysql-parallel-query-sql-subqueries)
+ [UNION](#aurora-mysql-parallel-query-sql-union)
+ [檢視](#aurora-mysql-parallel-query-sql-views)
+ [資料處理語言 (DML) 陳述式](#aurora-mysql-parallel-query-sql-dml)
+ [交易和鎖定](#aurora-mysql-parallel-query-sql-transactions)
+ [B 型樹狀結構索引](#aurora-mysql-parallel-query-sql-indexes)
+ [全文搜尋 (FTS) 索引](#aurora-mysql-parallel-query-sql-fts)
+ [虛擬資料欄](#aurora-mysql-parallel-query-sql-virtual-column)
+ [內建快取機制](#aurora-mysql-parallel-query-sql-caching)
+ [最佳化工具提示](#aurora-mysql-parallel-query-hints)
+ [MyISAM 暫存資料表](#aurora-mysql-parallel-query-sql-myisam)

## EXPLAIN 陳述式
<a name="aurora-mysql-parallel-query-sql-explain"></a>

 如本節中的範例所示，`EXPLAIN` 陳述式指出查詢的每個階段目前是否符合平行查詢的資格。該陳述式也會指出查詢的哪些層面可以下推至儲存層。解釋計劃中的最重要項目如下：
+  在 `NULL` 資料欄中，`key` 以外的值表示使用索引查詢才能有效地執行查詢，而不是平行查詢。
+  `rows` 資料欄若值不大 (亦即，不是數百萬的值) 代表查詢未存取足夠資料，平行查詢不值得執行，因此不可能進行平行查詢。這代表不太可能進行平行查詢。
+  `Extra` 資料欄顯示是否預期要使用平行查詢。此輸出看起來如以下範例所示。

  ```
  Using parallel query (A columns, B filters, C exprs; D extra)
  ```

   `columns` 數字代表查詢區塊中參照多少資料欄。

   `filters` 數字代表 `WHERE` 述詞的數目，而這些述詞代表資料欄值與常數的簡單比較。比較可用於等式、不等式或範圍。Aurora 可以最有效地平行化這些類型的述詞。

   `exprs` 數字代表表達式 (例如函數呼叫、運算子或其他也可以平行化的表達式) 的數目，但是不如篩選條件一樣有效。

   `extra` 數字代表不能下推且由前端節點執行的表達式數目。

 例如，考量以下 `EXPLAIN` 輸出。

```
mysql> explain select p_name, p_mfgr from part
    -> where p_brand is not null
    -> and upper(p_type) is not null
    -> and round(p_retailprice) is not null;
+----+-------------+-------+...+----------+----------------------------------------------------------------------------+
| id | select_type | table |...| rows     | Extra                                                                      |
+----+-------------+-------+...+----------+----------------------------------------------------------------------------+
|  1 | SIMPLE      | part  |...| 20427936 | Using where; Using parallel query (5 columns, 1 filters, 2 exprs; 0 extra) |
+----+-------------+-------+...+----------+----------------------------------------------------------------------------+
```

 來自 `Extra` 資料欄的資訊顯示，從每一個資料列擷取五個資料欄，以評估查詢條件並建構結果集。一個 `WHERE` 述詞涉及一個篩選條件，亦即，一個直接在 `WHERE` 子句中測試的資料欄。在此涉及函數呼叫的情況下，兩個 `WHERE` 子句需要評估更複雜的表達式。`0 extra` 欄位確認 `WHERE` 子句中的所有操作都下推至儲存層，做為平行查詢處理的部分。

 在未選擇平行查詢的情況下，您通常可以從 `EXPLAIN` 輸出的其他資料欄推斷原因。例如，`rows` 值可能太小，或 `possible_keys` 資料欄可能指出查詢可以使用索引查詢，而不是資料密集掃描。下例示範的查詢中，最佳化程式可以估計查詢將只掃描少量的資料行。它會根據主要金鑰的特性來執行此操作。在此情況下，不需要平行查詢。

```
mysql> explain select count(*) from part where p_partkey between 1 and 100;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | part  | range | PRIMARY       | PRIMARY | 4       | NULL |   99 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
```

 顯示是否將使用平行查詢的輸出會將 `EXPLAIN` 陳述式執行時所有可用的因素納入考量。當查詢實際執行時，如果情況同時變更，則最佳化器可能做出不同的選擇。例如，`EXPLAIN` 可能報告陳述式將使用平行查詢。但是，當查詢稍後實際執行時，根據那時的條件可能不使用平行查詢。這類條件可以包括同時執行的數個其他平行查詢。它們也可以包括從資料表中刪除的資料列、正在建立的新索引、在開啟的交易中傳遞太多的時間，以此類推。

## WHERE 子句
<a name="aurora-mysql-parallel-query-sql-where"></a>

 對於使用平行查詢最佳化的查詢，它*必須*包括一個 `WHERE` 子句。

 平行查詢最佳化可加速多種在 `WHERE` 子句中使用的表達式：
+  資料欄值與常數的簡單比較，稱為*篩選條件*。這些比較從下推至儲存層中受益最多。`EXPLAIN` 輸出中會報告查詢中篩選條件表達式的數目。
+  `WHERE` 子句中其他類型的表達式也會儘可能下推至儲存層。`EXPLAIN` 輸出中會報告查詢中這類表達式的數目。這些表達式可以是函數呼叫、`LIKE` 運算子、`CASE` 表達式等等。
+  平行查詢目前不會下推特定函數和運算子。查詢中這類表達式的數目會報告為 `extra` 輸出中的 `EXPLAIN` 計數器。查詢的其餘部分仍可以使用平行查詢。
+  未下推選取清單中的表達式時，包含這類函數的查詢仍可從平行查詢的中繼結果減少網路流量中受益。例如，呼叫選取清單中彙總函數的查詢可從平行查詢中受益，即使未下推彙總函數也一樣。

 例如，以下查詢執行完整資料表掃描，並處理 `P_BRAND` 資料欄的所有值。不過，它不會使用平行查詢，因為查詢未包括任何 `WHERE` 子句。

```
mysql> explain select count(*), p_brand from part group by p_brand;
+----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows     | Extra                           |
+----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+
|  1 | SIMPLE      | part  | ALL  | NULL          | NULL | NULL    | NULL | 20427936 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+
```

 反之，以下查詢包括篩選結果的 `WHERE` 述詞，因此可以套用平行查詢：

```
mysql> explain select count(*), p_brand from part where p_name is not null
    ->   and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000
    -> group by p_brand;
+----+...+----------+-------------------------------------------------------------------------------------------------------------+
| id |...| rows     | Extra                                                                                                       |
+----+...+----------+-------------------------------------------------------------------------------------------------------------+
|  1 |...| 20427936 | Using where; Using temporary; Using filesort; Using parallel query (5 columns, 1 filters, 2 exprs; 0 extra) |
+----+...+----------+-------------------------------------------------------------------------------------------------------------+
```

 如果最佳化器預估針對查詢區塊傳回的資料列數目很小，則平行查詢不會用於該查詢區塊。以下範例顯示一種案例，其中主要索引鍵資料欄上的大於運算子套用至數百萬個資料列，因而導致使用平行查詢。預估反向小於測試僅套用至少數資料列，因此不會使用平行查詢。

```
mysql> explain select count(*) from part where p_partkey > 10;
+----+...+----------+----------------------------------------------------------------------------+
| id |...| rows     | Extra                                                                      |
+----+...+----------+----------------------------------------------------------------------------+
|  1 |...| 20427936 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+----------+----------------------------------------------------------------------------+

mysql> explain select count(*) from part where p_partkey < 10;
+----+...+------+--------------------------+
| id |...| rows | Extra                    |
+----+...+------+--------------------------+
|  1 |...|    9 | Using where; Using index |
+----+...+------+--------------------------+
```

## 資料定義語言 (DDL)
<a name="aurora-mysql-parallel-query-sql-ddl"></a>

在 Aurora MySQL 第 2 版，平行查詢只適用於未擱置任何快速資料定義語言 (DDL) 作業的資料表。在 Aurora MySQL 第 3 版中，您可以同時在資料表上使用並行查詢，做為即時 DDL 作業。

Aurora MySQL 第 3 版中的即時 DDL 取代了 Aurora MySQL 第 2 版中的快速 DDL 功能。如需即時 DDL 的相關資訊，請參閱[即時 DDL (Aurora MySQL 第 3 版)](AuroraMySQL.Managing.FastDDL.md#AuroraMySQL.mysql80-instant-ddl)。

## 資料欄資料類型
<a name="aurora-mysql-parallel-query-sql-datatypes"></a>

 在 Aurora MySQL 第 3 版中，平行查詢可以使用包含資料欄的資料表，資料類型為 `TEXT`、`BLOB`、`JSON` 和 `GEOMETRY`。它也可以使用最大宣告長度超過 768 個位元組的 `VARCHAR` 和 `CHAR` 資料欄。如果您的查詢參照任何包含此類大型物件類型的資料欄，則擷取它們的額外工作確實會為查詢處理增加一些負荷。在此情況下，檢查查詢是否可以省略對這些資料欄的參照。如果不可以，請執行基準化分析，以確認在平行查詢開啟或關閉的情況下，這類查詢是否更快。

在 Aurora MySQL 第 2 版，平行查詢對於大型物件類型具有以下限制：
+ 不支援 `TEXT`、`BLOB`、`JSON` 和 `GEOMETRY` 資料類型搭配平行查詢使用。查詢若參照這些類型的任何資料欄，則無法使用平行查詢。
+ 可變長度資料欄 (`VARCHAR` 及 `CHAR` 資料類型) 與平行查詢相容，而宣告的長度最多可為 768 個位元組。查詢若參照以更長長度上限宣告之類型的任何資料欄，則無法使用平行查詢。對於使用多位元組字元集的資料欄，位元組限制會將字元集的位元組數目上限納入考量。例如，對於字元集 `utf8mb4` (字元長度上限為 4 個位元組)，`VARCHAR(192)` 資料欄與平行查詢相容，但 `VARCHAR(193)` 資料欄與其不相容。

## 分割的資料表
<a name="aurora-mysql-parallel-query-sql-partitioning"></a>

 在 Aurora MySQL 第 3 版中，您可以使用分割的資料表搭配平行查詢。因為分割的資料表在內部表示為多個較小的資料表，所以在非分割的資料表上使用平行查詢的查詢可能不會在相同的分割資料表上使用平行查詢。Aurora MySQL 會考慮每個分割區是否足夠大到有資格進行平行查詢最佳化，而不是評估整個資料表的大小。當您預期分割資料表上的查詢會使用平行查詢時，若未使用平行查詢，請檢查 `Aurora_pq_request_not_chosen_small_table` 狀態變數是否增加。

 例如，考慮一個使用 `PARTITION BY HASH (column) PARTITIONS 2` 分割的資料表，以及另一個使用 `PARTITION BY HASH (column) PARTITIONS 10` 分割的資料表。在具有兩個分割區的資料表中，這些分割區是具有十個分割區之資料表的五倍大。因此，平行查詢更有可能用於針對分割區較少之資料表的查詢。在下列範例中，資料表 `PART_BIG_PARTITIONS` 有兩個分割區，而 `PART_SMALL_PARTITIONS` 有十個分割區。使用相同的資料，平行查詢更有可能用於大型分割區較少的資料表。

```
mysql> explain select count(*), p_brand from part_big_partitions where p_name is not null
    ->   and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000 group by p_brand;
+----+-------------+---------------------+------------+-------------------------------------------------------------------------------------------------------------------+
| id | select_type | table               | partitions | Extra                                                                                                             |
+----+-------------+---------------------+------------+-------------------------------------------------------------------------------------------------------------------+
|  1 | SIMPLE      | part_big_partitions | p0,p1      | Using where; Using temporary; Using parallel query (4 columns, 1 filters, 1 exprs; 0 extra; 1 group-bys, 1 aggrs) |
+----+-------------+---------------------+------------+-------------------------------------------------------------------------------------------------------------------+

mysql> explain select count(*), p_brand from part_small_partitions where p_name is not null
    ->   and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000 group by p_brand;
+----+-------------+-----------------------+-------------------------------+------------------------------+
| id | select_type | table                 | partitions                    | Extra                        |
+----+-------------+-----------------------+-------------------------------+------------------------------+
|  1 | SIMPLE      | part_small_partitions | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9 | Using where; Using temporary |
+----+-------------+-----------------------+-------------------------------+------------------------------+
```

## 彙整函數、GROUP BY 子句和 HAVING 子句
<a name="aurora-mysql-parallel-query-sql-aggregation"></a>

 涉及彙線函數的查詢通常是平行查詢的理想候選者，因為它們涉及掃描大型資料表內的大量資料列。

 在 Aurora MySQL 3 中，平行查詢可以在選取清單和 `HAVING` 子句中最佳化彙總函數呼叫。

 在 Aurora MySQL 3 之前，選取清單或 `HAVING` 子句中的彙總函數呼叫不會下推至儲存層。不過，平行查詢仍可以利用彙總函數改善這類查詢的效能。其做法是首先從儲存層的原始資料頁面中平行擷取資料欄值。然後，它會以壓縮的 Tuple 格式而不是整個資料頁面，將那些值傳回至前端節點。一如往常，查詢需要至少一個 `WHERE` 述詞，才能啟動平行查詢。

 以下簡單範例說明哪些類型的彙總查詢可從平行查詢受益。其做法是以壓縮格式將中繼結果傳回至前端節點、篩選中繼結果中不相符的資料列，或兩者。

```
mysql> explain select sql_no_cache count(distinct p_brand) from part where p_mfgr = 'Manufacturer#5';
+----+...+----------------------------------------------------------------------------+
| id |...| Extra                                                                      |
+----+...+----------------------------------------------------------------------------+
|  1 |...| Using where; Using parallel query (2 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+----------------------------------------------------------------------------+

mysql> explain select sql_no_cache p_mfgr from part where p_retailprice > 1000 group by p_mfgr having count(*) > 100;
+----+...+-------------------------------------------------------------------------------------------------------------+
| id |...| Extra                                                                                                       |
+----+...+-------------------------------------------------------------------------------------------------------------+
|  1 |...| Using where; Using temporary; Using filesort; Using parallel query (3 columns, 0 filters, 1 exprs; 0 extra) |
+----+...+-------------------------------------------------------------------------------------------------------------+
```

## WHERE 子句中的函數呼叫
<a name="aurora-mysql-parallel-query-sql-functions"></a>

 Aurora 可將平行查詢最佳化套用至對 `WHERE` 子句中大部分內建函數的呼叫。平行化這些函數呼叫可從前端節點中卸載一些 CPU 工作。在最早查詢階段期間平行評估述詞函數，可協助 Aurora 將後續階段期間傳輸和處理的資料量降至最低。

 目前，平行化不適用於選取清單中的函數呼叫。那些函數是由前端節點評估，即使相同的函數呼叫出現在 `WHERE` 子句中也一樣。來自相關資料欄的原始值會併入從儲存節點傳回至前端節點的 Tuple 中。前端節點會執行任何轉換 (例如 `UPPER`、`CONCATENATE` 等等)，以產生結果集的最終值。

 在以下範例中，平行查詢會平行化對 `LOWER` 的呼叫，因為它出現在 `WHERE` 子句中。平行查詢不會影響對 `SUBSTR` 和 `UPPER` 的呼叫，因為它們會顯示在選取清單中。

```
mysql> explain select sql_no_cache distinct substr(upper(p_name),1,5) from part
    -> where lower(p_name) like '%cornflower%' or lower(p_name) like '%goldenrod%';
+----+...+---------------------------------------------------------------------------------------------+
| id |...| Extra                                                                                       |
+----+...+---------------------------------------------------------------------------------------------+
|  1 |...| Using where; Using temporary; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) |
+----+...+---------------------------------------------------------------------------------------------+
```

 相同考量適用於其他表達式，例如 `CASE` 表達式或 `LIKE` 運算子。例如，以下範例顯示平行查詢評估 `CASE` 子句中的 `LIKE` 表達式和 `WHERE` 運算子。

```
mysql> explain select p_mfgr, p_retailprice from part
    -> where p_retailprice > case p_mfgr
    ->   when 'Manufacturer#1' then 1000
    ->   when 'Manufacturer#2' then 1200
    ->   else 950
    -> end
    -> and p_name like '%vanilla%'
    -> group by p_retailprice;
+----+...+-------------------------------------------------------------------------------------------------------------+
| id |...| Extra                                                                                                       |
+----+...+-------------------------------------------------------------------------------------------------------------+
|  1 |...| Using where; Using temporary; Using filesort; Using parallel query (4 columns, 0 filters, 2 exprs; 0 extra) |
+----+...+-------------------------------------------------------------------------------------------------------------+
```

## LIMIT 子句
<a name="aurora-mysql-parallel-query-sql-limit"></a>

 目前，平行查詢不會用於任何包含 `LIMIT` 子句的查詢區塊。平行查詢仍然可以透過 `GROUP` 或聯結搭配 `ORDER BY` 使用早期的查詢階段。

## 比較運算子
<a name="aurora-mysql-parallel-query-sql-comparisons"></a>

 最佳化器會預估要掃描多少資料列來評估比較運算子，並根據該預估來判定是否要使用平行查詢。

 以下第一個範例顯示在沒有平行查詢的情況下，可以有效地執行針對主要索引鍵資料欄的等式比較。以下第二個範例顯示針對未檢索資料欄的類似比較需要掃描數百萬個資料列，因此可從平行查詢中受益。

```
mysql> explain select * from part where p_partkey = 10;
+----+...+------+-------+
| id |...| rows | Extra |
+----+...+------+-------+
|  1 |...|    1 | NULL  |
+----+...+------+-------+

mysql> explain select * from part where p_type = 'LARGE BRUSHED BRASS';
+----+...+----------+----------------------------------------------------------------------------+
| id |...| rows     | Extra                                                                      |
+----+...+----------+----------------------------------------------------------------------------+
|  1 |...| 20427936 | Using where; Using parallel query (9 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+----------+----------------------------------------------------------------------------+
```

 相同考量適用於不等於測試，也適用於範圍比較，例如小於、大於或等於，或 `BETWEEN`。最佳化器會預估要掃描的資料列數目，並根據輸入/輸出的整體數量來判定平行查詢是否值得。

## 聯結
<a name="aurora-mysql-parallel-query-sql-joins"></a>

 具有大型資料表的聯結查詢通常涉及可從平行查詢最佳化中受益的資料密集操作。目前不會平行化多個資料表之間的資料欄值比較 (亦即，聯結述詞本身)。不過，平行查詢可以下推其他聯結階段的某些內部處理，例如在雜湊聯結期間建構 Bloom 篩選條件。即使沒有 `WHERE` 子句，平行查詢也可以套用至聯結查詢。因此，聯結查詢是 `WHERE` 子句需要使用平行查詢之規則的例外。

 聯結處理的每個階段都會進行評估，以檢查它是否符合平行查詢的資格。如果多個階段可以使用平行查詢，則會依序執行這些階段。因此，根據並行限制，每個聯結查詢都會視為單一平行查詢工作階段。

 例如，當聯結查詢包括 `WHERE` 述詞，來篩選其中一個聯結資料表中的資料列時，該篩選選項可以使用平行查詢。另一個範例是假設聯結查詢使用雜湊聯結機制，例如來聯結大型資料表與小型資料表。在此情況下，產生 Bloom 篩選條件資料結構的資料表掃描或許能夠使用平行查詢。

**注意**  
 受益於雜湊聯結最佳化的資源密集型查詢，通常使用平行查詢。開啟雜湊聯結最佳化的方法取決於 Aurora MySQL 版本。如需每個版本的詳細資訊，請參閱[開啟平行查詢叢集的雜湊聯結](aurora-mysql-parallel-query-enabling.md#aurora-mysql-parallel-query-enabling-hash-join)。如需如何有效使用雜湊聯結的相關資訊，請參閱[使用雜湊聯結，將大型 Aurora MySQL 聯結查詢最佳化](AuroraMySQL.BestPractices.Performance.md#Aurora.BestPractices.HashJoin)。

```
mysql> explain select count(*) from orders join customer where o_custkey = c_custkey;
+----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+
| id |...| table    | type  | possible_keys | key         |...| rows      | Extra                                                                                                           |
+----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+
|  1 |...| customer | index | PRIMARY       | c_nationkey |...|  15051972 | Using index                                                                                                     |
|  1 |...| orders   | ALL   | o_custkey     | NULL        |...| 154545408 | Using join buffer (Hash Join Outer table orders); Using parallel query (1 columns, 0 filters, 1 exprs; 0 extra) |
+----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+
```

 對於使用巢狀迴圈機制的聯結查詢，最外層的巢狀迴圈區塊可能使用平行查詢。是否使用平行查詢取決於與往常相同的因素，例如 `WHERE` 子句中是否存在額外的篩選條件。

```
mysql> -- Nested loop join with extra filter conditions can use parallel query.
mysql> explain select count(*) from part, partsupp where p_partkey != ps_partkey and p_name is not null and ps_availqty > 0;
+----+-------------+----------+...+----------+----------------------------------------------------------------------------+
| id | select_type | table    |...| rows     | Extra                                                                      |
+----+-------------+----------+...+----------+----------------------------------------------------------------------------+
|  1 | SIMPLE      | part     |...| 20427936 | Using where; Using parallel query (2 columns, 1 filters, 0 exprs; 0 extra) |
|  1 | SIMPLE      | partsupp |...| 78164450 | Using where; Using join buffer (Block Nested Loop)                         |
+----+-------------+----------+...+----------+----------------------------------------------------------------------------+
```

## 子查詢
<a name="aurora-mysql-parallel-query-sql-subqueries"></a>

 外部查詢區塊和內部子查詢區塊可能每個使用平行查詢，或者不使用。他們是否會這樣做，需視資料表、`WHERE` 子句等對每個區塊來說的通常特徵而定。例如，以下查詢會針對子查詢區塊，但不會針對外部區塊使用平行查詢。

```
mysql> explain select count(*) from part where
   --> p_partkey < (select max(p_partkey) from part where p_name like '%vanilla%');
+----+-------------+...+----------+----------------------------------------------------------------------------+
| id | select_type |...| rows     | Extra                                                                      |
+----+-------------+...+----------+----------------------------------------------------------------------------+
|  1 | PRIMARY     |...|     NULL | Impossible WHERE noticed after reading const tables                        |
|  2 | SUBQUERY    |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) |
+----+-------------+...+----------+----------------------------------------------------------------------------+
```

 目前，相關的子查詢無法使用平行查詢最佳化。

## UNION
<a name="aurora-mysql-parallel-query-sql-union"></a>

 根據 `UNION` 每個部分之資料表、`WHERE` 子句等等的一般特性，`UNION` 查詢中的每個查詢區塊可以或不可以使用平行查詢。

```
mysql> explain select p_partkey from part where p_name like '%choco_ate%'
    -> union select p_partkey from part where p_name like '%vanil_a%';
+----+----------------+...+----------+----------------------------------------------------------------------------+
| id | select_type    |...| rows     | Extra                                                                      |
+----+----------------+...+----------+----------------------------------------------------------------------------+
|  1 | PRIMARY        |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) |
|  2 | UNION          |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) |
| NULL | UNION RESULT | <union1,2> |...|     NULL | Using temporary                                           |
+----+--------------+...+----------+----------------------------------------------------------------------------+
```

**注意**  
 查詢內的每個 `UNION` 子句都會循序執行。即使查詢包括多個全都使用平行查詢的階段，它在任何情況下都只會執行單一平行查詢。因此，即使複雜的多階段查詢也會當做 1 計入並行平行查詢的限制之中。

## 檢視
<a name="aurora-mysql-parallel-query-sql-views"></a>

 最佳化器會使用檢視做為使用基礎資料表的更長查詢，來重新撰寫任何查詢。因此，無論資料表參照是檢視還是真正資料表，平行查詢的運作方式都相同。關於是否要在查詢中使用平行查詢，以及下推哪些部分的所有相同考量，都適用於最終重新撰寫的查詢。

 例如，以下解釋計劃顯示通常不會使用平行查詢的檢視定義。利用額外的 `WHERE` 子句來查詢該檢視時，Aurora MySQL 會使用平行查詢。

```
mysql> create view part_view as select * from part;
mysql> explain select count(*) from part_view where p_partkey is not null;
+----+...+----------+----------------------------------------------------------------------------+
| id |...| rows     | Extra                                                                      |
+----+...+----------+----------------------------------------------------------------------------+
|  1 |...| 20427936 | Using where; Using parallel query (1 columns, 0 filters, 0 exprs; 1 extra) |
+----+...+----------+----------------------------------------------------------------------------+
```

## 資料處理語言 (DML) 陳述式
<a name="aurora-mysql-parallel-query-sql-dml"></a>

 如果 `INSERT` 部分符合平行查詢的其他條件，則 `SELECT` 陳述式可對處理的 `SELECT` 階段使用平行查詢。

```
mysql> create table part_subset like part;
mysql> explain insert into part_subset select * from part where p_mfgr = 'Manufacturer#1';
+----+...+----------+----------------------------------------------------------------------------+
| id |...| rows     | Extra                                                                      |
+----+...+----------+----------------------------------------------------------------------------+
|  1 |...| 20427936 | Using where; Using parallel query (9 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+----------+----------------------------------------------------------------------------+
```

**注意**  
 通常，在 `INSERT` 陳述式之後，新插入之資料列的資料位於緩衝集區中。因此，在插入大量資料列之後，資料表可能無法立即符合平行查詢的資格。稍後，在正常操作期間從緩衝集區移出資料之後，針對資料表的查詢可能開始再次使用平行查詢。

 即使 `CREATE TABLE AS SELECT` 陳述式的 `SELECT` 部分將符合平行查詢的資格，此陳述式也不會使用平行查詢。此陳述式的 DDL 層面使得它與平行查詢處理不相容。反之，在 `INSERT ... SELECT` 陳述式中，`SELECT` 部分可以使用平行查詢。

 無論 `DELETE`子句中資料表和述詞的大小為何，平行查詢決不用於 `UPDATE` 或 `WHERE` 陳述式。

```
mysql> explain delete from part where p_name is not null;
+----+-------------+...+----------+-------------+
| id | select_type |...| rows     | Extra       |
+----+-------------+...+----------+-------------+
|  1 | SIMPLE      |...| 20427936 | Using where |
+----+-------------+...+----------+-------------+
```

## 交易和鎖定
<a name="aurora-mysql-parallel-query-sql-transactions"></a>

 您可以在 Aurora 主要執行個體上使用所有隔離層級。

在 Aurora 讀取器資料庫執行個體上，平行查詢會套用至 `REPEATABLE READ` 隔離層級下執行的陳述式。Aurora MySQL 版本 2.09 或更新版本也可以在讀取器資料庫執行個體上使用 `READ COMMITTED` 隔離級別。`REPEATABLE READ` 是 Aurora 讀取器資料庫執行個體的預設隔離等級。若要在讀取器資料庫執行個體上使用 `READ COMMITTED` 隔離等級，您需要在工作階段層級設定 `aurora_read_replica_read_committed` 組態選項。讀取器執行個體的 `READ COMMITTED` 隔離層級符合 SQL 標準行為。不過，讀取器執行個體上的隔離不太嚴格，但當查詢在寫入器執行個體上使用 `READ COMMITTED` 隔離層級時更為嚴格。

 如需 Aurora 隔離層級的詳細資訊，尤其是 `READ COMMITTED` 之間的差異，請參閱 [Aurora MySQL 隔離層級](AuroraMySQL.Reference.IsolationLevels.md)。

 在完成大型交易之後，資料表統計資料可能過時。這類過時的統計資料可能需要 `ANALYZE TABLE` 陳述式，然後 Aurora 才能精確地預估資料列數目。大規模的 DML 陳述式也可能將資料表資料的很大一部分帶入緩衝集區中。在緩衝集區中具有此資料，可能導致不常針對該資料表選擇平行查詢，直到從集區移出資料。

 當您的工作階段是在長時間執行的交易 (預設為 10 分鐘) 內時，該工作階段內的進一步查詢不會使用平行查詢。在單一長時間執行的查詢期間也可能發生逾時。在平行查詢處理開始之前，如果查詢的執行時間超過間隔上限 (目前為 10 分鐘)，則此類型的逾時可能會發生。

 您可以在執行臨時 (一次性) 查詢的 `autocommit=1` 工作階段中設定 `mysql`，來減少意外啟動長時間執行之交易的機會。針對資料表的 `SELECT` 陳述式甚至會建立讀取檢視來開始交易。*讀取檢視*是適用於後續查詢的一致資料集，一直留到確定交易為止。使用 JDBC 或 ODBC 應用程式與 Aurora 搭配時，請注意此限制，因為應用程式可能在 `autocommit` 設定關閉的情況下執行。

 以下範例顯示在 `autocommit` 設定關閉的情況下，針對資料表執行查詢時，如何建立隱含地開始交易的讀取檢視。之後短暫執行的查詢仍可以使用平行查詢。不過，在暫停數分鐘之後，查詢不再符合平行查詢的資格。利用 `COMMIT` 或 `ROLLBACK` 結束交易，可還原平行查詢資格。

```
mysql> set autocommit=0;

mysql> explain select sql_no_cache count(*) from part where p_retailprice > 10.0;
+----+...+---------+----------------------------------------------------------------------------+
| id |...| rows    | Extra                                                                      |
+----+...+---------+----------------------------------------------------------------------------+
|  1 |...| 2976129 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+---------+----------------------------------------------------------------------------+

mysql> select sleep(720); explain select sql_no_cache count(*) from part where p_retailprice > 10.0;
+------------+
| sleep(720) |
+------------+
|          0 |
+------------+
1 row in set (12 min 0.00 sec)

+----+...+---------+-------------+
| id |...| rows    | Extra       |
+----+...+---------+-------------+
|  1 |...| 2976129 | Using where |
+----+...+---------+-------------+

mysql> commit;

mysql> explain select sql_no_cache count(*) from part where p_retailprice > 10.0;
+----+...+---------+----------------------------------------------------------------------------+
| id |...| rows    | Extra                                                                      |
+----+...+---------+----------------------------------------------------------------------------+
|  1 |...| 2976129 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+---------+----------------------------------------------------------------------------+
```

 若要查看查詢有多少次未符合平行查詢的資格，因為它們是在長時間執行的交易內，請檢查狀態變數 `Aurora_pq_request_not_chosen_long_trx`。

```
mysql> show global status like '%pq%trx%';
+---------------------------------------+-------+
| Variable_name                         | Value |
+---------------------------------------+-------+
| Aurora_pq_request_not_chosen_long_trx | 4     |
+-------------------------------+-------+
```

 任何獲得鎖定的 `SELECT` 陳述式 (例如 `SELECT FOR UPDATE` 或 `SELECT LOCK IN SHARE MODE` 語法) 都無法使用平行查詢。

 平行查詢可以用於 `LOCK TABLES` 陳述式鎖定的資料表。

```
mysql> explain select o_orderpriority, o_shippriority from orders where o_clerk = 'Clerk#000095055';
+----+...+-----------+----------------------------------------------------------------------------+
| id |...| rows      | Extra                                                                      |
+----+...+-----------+----------------------------------------------------------------------------+
|  1 |...| 154545408 | Using where; Using parallel query (3 columns, 1 filters, 0 exprs; 0 extra) |
+----+...+-----------+----------------------------------------------------------------------------+

mysql> explain select o_orderpriority, o_shippriority from orders where o_clerk = 'Clerk#000095055' for update;
+----+...+-----------+-------------+
| id |...| rows      | Extra       |
+----+...+-----------+-------------+
|  1 |...| 154545408 | Using where |
+----+...+-----------+-------------+
```

## B 型樹狀結構索引
<a name="aurora-mysql-parallel-query-sql-indexes"></a>

 `ANALYZE TABLE` 陳述式收集的統計資料可協助最佳化器根據每個資料欄的資料特性，決定何時使用平行查詢或索引查閱。在對資料表內的資料進行大幅變更的 DML 操作之後，請執行 `ANALYZE TABLE` 來保持最新的統計資料。

 如果索引檢閱可以有效執行查詢，而沒有資料密集掃描，則 Aurora 可能使用索引檢閱。這樣做可以避免平行查詢處理的額外負荷。對於可在任何 Aurora 資料庫叢集上同時執行的平行查詢數目也有並行限制。確定使用最佳實務來製作資料表的索引，讓您最常使用和最高度並行的查詢可以使用索引檢閱。

## 全文搜尋 (FTS) 索引
<a name="aurora-mysql-parallel-query-sql-fts"></a>

 目前，平行查詢不會用於包含全文搜尋索引的資料表，無論查詢是參照這類索引資料欄，還是使用 `MATCH` 運算子。

## 虛擬資料欄
<a name="aurora-mysql-parallel-query-sql-virtual-column"></a>

 目前，平行查詢不會用於包含虛擬資料欄的資料表，無論查詢是否參考任何虛擬資料欄。

## 內建快取機制
<a name="aurora-mysql-parallel-query-sql-caching"></a>

 Aurora 包括內建快取機制，即緩衝集區和查詢快取。Aurora 最佳化器會在這些快取機制進行選擇，並根據哪一個機制對特定查詢最有效來選擇平行查詢。

 當平行查詢篩選資料列，以及轉換並擷取資料欄值時，資料會傳回至前端節點，做為 Tuple 而非做為資料頁面。因此，執行平行查詢不會新增任何頁面至緩衝集區，或移出已在緩衝集區的頁面。

 Aurora 會檢查緩衝集區中呈現的資料表頁面數目，以及該數目代表多少比例的資料表資料。Aurora 會使用該資訊來決定，使用平行查詢 (以及略過緩衝集區中的資料) 是否更有效。或者，Aurora 可能使用非平行查詢處理路徑，這會使用緩衝集區中快取的資料。快取哪些頁面和資料密集查詢如何影響快取及移出，取決於與緩衝集區相關的組態設定。因此，難以預測任何查詢是否使用平行查詢，因為選擇取決於緩衝集區內不斷變更的資料。

 此外，Aurora 也會對平行查詢強加並行限制。因為不是每個查詢都會使用平行查詢，所以多個查詢同時存取的資料表通常會具有緩衝集區中資料的很大一部分。因此，Aurora 通常不會選擇這些資料表進行平行查詢。

 當您在相同的資料表上執行一連串的非平行查詢時，由於資料未在緩衝集區中，第一個查詢可能很慢。然後，第二個與後續查詢會快得多，因為緩衝集區現在完成了「暖機」。從最初針對資料表的第一個查詢開始，平行查詢通常會顯示一致的效能。當進行效能測試時，會同時使用冷和暖緩衝集區，對非平行查詢進行基準測試。在某些情況下，具有暖緩衝集區的結果可以充分地與平行查詢時間進行比較。在這些情況下請考慮因素，例如針對該資料表的查詢頻率。也請考慮是否值得將該資料表的資料保留在緩衝集區中。

 當提交相同的查詢，以及基礎資料表的資料未變更時，查詢快取可避免重新執行查詢。由平行查詢功能最佳化的查詢可以移至查詢快取，如此可在重新執行時有效地讓它們成為即時查詢。

**注意**  
 進行效能比較時，查詢快取可以產生人為的低時序數。因此，在類似基準測試的情況中，您可以使用 `sql_no_cache` 提示。此提示可防止從查詢快取提供結果，即使先前已執行相同的查詢也一樣。提示緊跟在查詢中的 `SELECT` 陳述式後面。本主題中的許多平行查詢範例都包括此提示，以使得可在平行查詢開啟和關閉的查詢版本之間進行查詢時間比較。  
 當您移至生產用途的平行查詢時，確定從您的來源中移除此提示。

## 最佳化工具提示
<a name="aurora-mysql-parallel-query-hints"></a>

控制最佳化工具的另一種方式是使用最佳化工具提示，您可以在個別陳述式中指定這些提示。例如，您可以在一個陳述式中為一份資料表開啟最佳化，為另一份資料表關閉最佳化。如需這些提示的詳細資訊，請參閱《MySQL 參考手冊》**中的[最佳化工具提示](https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html)。

您可以將 SQL 提示與 Aurora MySQL 查詢搭配使用，以微調效能。您也可以使用提示來防止重要查詢的執行計劃因不可預期的情況而變更。

我們已擴充 SQL 提示功能，協助您控制查詢計畫的最佳化工具選擇。這些提示適用於使用平行查詢最佳化的查詢。如需更多詳細資訊，請參閱 [Aurora MySQL 提示](AuroraMySQL.Reference.Hints.md)。

## MyISAM 暫存資料表
<a name="aurora-mysql-parallel-query-sql-myisam"></a>

平行查詢最佳化僅適用於 InnoDB 資料表。因為 Aurora MySQL 會在幕後針對暫時資料表使用 MyISAM，所以涉及暫時資料表的內部查詢階段永遠不會使用平行查詢。這些查詢階段是由 `Using temporary` 輸出中的 `EXPLAIN` 指出。