Aurora MySQL の並列クエリ用の SQL コンストラクト
このセクションでは、特定の SQL ステートメントでパラレルクエリが使用される理由と使用されない理由について詳しく説明します。また、Aurora MySQL の機能とパラレルクエリのインタラクションについても説明します。これらの内容は、パラレルクエリを使用するクラスターのパフォーマンスの問題を診断したり、特定のワークロードにパラレルクエリがどのように適用されるかを理解したりするために役立ちます。
パラレルクエリを使用するかどうかの決定は、ステートメントが実行される時点で発生する多くの要因に依存します。したがって、パラレルクエリは、特定の条件の下で常に使用される、特定の条件の下では決して使用されない、または特定の条件の下でのみ使用される特定のクエリに対して使用される可能性があります。
ヒント
以下の例を HTML で表示している場合は、記載されている各コードの右上隅にあるコピーウィジェットを使用して SQL コードをコピーして使用することができます。このコピーウィジェットを使用すると、mysql>
プロンプトとそれに続く ->
の行の周りの余分な文字がコピーされません。
トピック
EXPLAIN ステートメント
このセクションの例で示すように、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
列の情報は、各行から 5 つの列が抽出され、クエリ条件を評価し結果セットを構成することを示しています。1 つの WHERE
述語にはフィルター、つまり WHERE
句で直接テストされた列が含まれます。2 つの 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 句
クエリがパラレルクエリの最適化を使用するには、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)
Aurora MySQL バージョン 2 では、パラレルクエリは、高速データ定義言語 (DDL) オペレーションが保留されていないテーブルでのみ利用可能です。Aurora MySQL バージョン 3 では、インスタント DDL オペレーションと同時にテーブルに対してパラレルクエリを使用できます。
Aurora MySQL バージョン 3 のインスタント DDL では、Aurora MySQL バージョン 2 の高速 DDL 機能が置き換えられます。DDL ステートメントの詳細については、インスタント DDL (Aurora MySQL バージョン 3) を参照してください。
列のデータ型
Aurora MySQL バージョン 3 では、パラレルクエリはデータタイプ TEXT
、BLOB
、JSON
、および GEOMETRY
のカラムを含むテーブルで使用できます。また、宣言された長さの最大数が 768 バイト以上の VARCHAR
、および CHAR
のカラムでも使用することが可能です。クエリがそのようなラージオブジェクトタイプを含む列を参照している場合、それを取得するための追加作業によってクエリ処理にオーバーヘッドが発生します。その場合、それらの列への参照をクエリが省略できるかチェックしてください。そうでない場合は、ベンチマークを実行し、パラレルクエリをオンまたはオフにしてた状態でこのようなクエリが高速であるかどうかを確認します。
Aurora MySQL バージョン 2 では、ラージオブジェクトタイプに対してパラレルクエリは次の制限があります。
-
TEXT
、BLOB
、JSON
、GEOMETRY
データ型は、並列クエリではサポートされていません。これらの型の列を参照するクエリは、並列クエリを使用できません。 -
可変長の列 (
VARCHAR
およびCHAR
) は、最大 768 バイトの宣言された最大長までの並列クエリと互換性があります。上記より長い最大長で宣言された型の列を参照するクエリは、並列クエリを使用できません。マルチバイト文字セットを使用する列の場合、バイト制限には文字セット内の最大バイト数が考慮されます。例えば、最大文字長が 4 バイトの文字セットutf8mb4
の場合、VARCHAR(192)
列はパラレルクエリと互換性がありますが、VARCHAR(193)
列は互換性はありません。
パーティションテーブル
Aurora MySQL バージョン 3 では、パーティショニングされたテーブルをパラレルクエリで使用できます。パーティショニングテーブルは内部的に複数の小さなテーブルとして表されるため、非パーティションテーブルに対してパラレルクエリを使用するクエリでは、同一のパーティショニングテーブルに対してパラレルクエリを使用しない場合があります。Aurora MySQL は、テーブル全体のサイズを評価するのではなく、各パーティションがパラレルクエリ最適化の対象となるのに十分な大きさがあるかどうかを検討します。パーティショニングテーブルのクエリがパラレルクエリを使用しない場合、Aurora_pq_request_not_chosen_small_table
ステータス 可変がインクリメントされているかどうかをチェックしてください。
例えば、PARTITION BY HASH (
でパーティショニングされている一つのテーブルと、column
) PARTITIONS 2PARTITION BY HASH (
でパーティション分散されている別のテーブルについて考えてみます。2 つのパーティションがあるテーブルでは、パーティションは 10 個のパーティションを持つテーブルの 5 倍になります。したがって、パラレルクエリは、パーティションがより少ないテーブルに対するクエリに使用される可能性が高くなります。次の例では、テーブル column
) PARTITIONS 10PART_BIG_PARTITIONS
には 2 つのパーティションがあり、PART_SMALL_PARTITIONS
には 10 個のパーティションがあります。同一データでは、大きなパーティションがより少ないテーブルに対してパラレルクエリは使用される可能性が高くなります。
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 句
集計関数を含むクエリは、大規模なテーブル内の多数の行をスキャンするため、パラレルクエリに適しています。
Aurora MySQL 3 では、パラレルクエリは選択リストと HAVING
句内の集計関数呼び出しを最適化できます。
Aurora MySQL 3 より前では、選択リストまたは HAVING
句の集計関数呼び出しはストレージレイヤーにプッシュダウンされませんでした。ただし、パラレルクエリは、集計関数を使用してこのようなクエリのパフォーマンスを向上させることができます。これは、初期にストレージレイヤーでパラレルに raw データページから列値を抽出することによって行われます。次に、それらの値をデータページ全体ではなくコンパクトなタプル形式でヘッドノードに戻します。今回も、クエリにはパラレルクエリを有効にするための少なくとも 1 つの 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 句での関数呼び出し
Aurora は、WHERE
句のほとんどの組み込み関数への呼び出しにパラレルクエリの最適化を適用できます。これらの関数呼び出しをパラレル化すると、いくつかの CPU 作業がヘッドノードからオフロードされます。最も早いクエリステージで述語関数を並行して評価することで、Aurora は後のステージで送信および処理されるデータ量を最小限に抑えることができます。
現在、パラレル化は選択リストの関数呼び出しには適用されません。これらの関数は、同じ関数呼び出しが WHERE
句に現れても、ヘッドノードによって評価されます。関連する列からの元の値は、ストレージノードからヘッドノードに送信されたタプルに含まれます。ヘッドノードは、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 句
現在のところ、LIMIT
句を含むクエリブロックでは、パラレルクエリは使用されません。GROUP
by、ORDER BY
、または結合を使用して、以前のクエリフェーズでもパラレルクエリを使用することができます。
比較演算子
オプティマイザは、比較演算子を評価するためにスキャンする行数を推定し、その推定値に基づいてパラレルクエリを使用するかどうかを決定します。
次の初期の例は、プライマリキー列との等価比較をパラレルクエリなしで効率的に実行できることを示しています。次の 2 番目の例では、インデックス作成されていない列に対する同様の比較では数百万行のスキャンが必要なため、パラレルクエリのメリットが得られます。
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
などの範囲比較にも同じ考慮事項が適用されます。オプティマイザは、スキャンする行数を推定し、I/O 全体の量に基づいてパラレルクエリが有効かどうかを判断します。
Joins
大きなテーブルを使用した結合クエリには、通常、パラレルクエリの最適化のメリットを受けるデータ集約型操作が含まれます。現在、複数のテーブル (つまり、結合述語自体) 間の列値の比較パラレルパラレル化されません。ただし、パラレルクエリは、ハッシュ結合中に Bloom フィルターを構築するなど、他の結合フェーズの内部処理の一部をプッシュダウンできます。パラレルクエリは、WHERE
句がなくても結合クエリに適用できます。したがって、結合クエリは、パラレルクエリを使用するために WHERE
句が必要であるという規則に対する例外です。
結合処理の各フェーズが評価され、パラレルクエリに適格であるかどうかがチェックされます。複数のフェーズでパラレルクエリを使用できる場合は、これらのフェーズが順番に実行されます。したがって、各結合クエリは、同時実行制限に関して単一のパラレルクエリセッションとしてカウントされます。
例えば、結合クエリが結合テーブルの 1 つから行をフィルタリングする WHERE
述語を含む場合、そのフィルタリングオプションはパラレルクエリを使用できます。別の例として、結合クエリがハッシュ結合メカニズムを使用するとします。例えば、大きなテーブルを小さなテーブルに結合する場合などです。この場合、Bloom フィルターデータ構造を生成するためのテーブルスキャンは、パラレルクエリを使用することができます。
注記
パラレルクエリは通常、ハッシュ結合の最適化による利点がある、大量のリソースを使用する種類のクエリに使用されます。ハッシュ結合の最適化を有効にする方法は、Aurora MySQL のバージョンによって異なります。各バージョンの詳細については、パラレルクエリクラスターのハッシュ結合の有効化 を参照してください。ハッシュ結合を効果的に使用する方法については、ハッシュ結合を使用した大規模な Aurora MySQL 結合クエリの最適化 を参照してください。
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) | +----+-------------+----------+...+----------+----------------------------------------------------------------------------+
サブクエリ
外部クエリブロックと内部サブクエリブロックでは、そのそれぞれでパラレルクエリを使用するかどうかが決定されます。各ブロックで使用するかどうかは、テーブルの通常の特徴や 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
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 つのパラレルクエリしか実行されません。したがって、複雑な複数ステージのクエリであっても、同時並行クエリの制限として 1 つだけカウントされます。
ビュー
オプティマイザは、基になるテーブルを使用して、より長いクエリとしてビューを使用するクエリをすべて書き換えます。したがって、パラレルクエリは、テーブル参照がビューでも実テーブルであっても同じように機能します。クエリに対してパラレルクエリを使用するかどうか、およびプッシュダウンする部分については、最終的に書き直されたクエリに同じ考慮事項が適用されます。
例えば、次のクエリプランは、通常はパラレルクエリを使用しないビューの定義を示しています。追加の 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) ステートメント
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 | +----+-------------+...+----------+-------------+
トランザクションとロック
すべての分離レベルは、Aurora プライマリインスタンスで使用できます。
Aurora リーダー DB インスタンスでは、パラレルクエリは REPEATABLE READ
の分離レベルの下で実行されるステートメントに適用されます。Aurora MySQL バージョン 2.09 以降では、リーダー DB インスタンスに対して READ COMMITTED
分離レベルも使用されます。REPEATABLE READ
は、Aurora リーダー DB インスタンスのデフォルトの分離レベルです。リーダー DB インスタンスで READ
COMMITTED
分離レベルを使用するには、セッションレベルで aurora_read_replica_read_committed
設定オプションを設定する必要があります。READ
COMMITTED
リーダーインスタンスの分離レベルは SQL のスタンダード動作に準拠しています。ただし、この分離は、クエリがライターインスタンスで READ COMMITTED
分離レベルを使用する場合よりも、リーダーインスタンスでは厳密ではありません。
Aurora の分離レベル、特にライターインスタンスとリーダーインスタンス間での READ COMMITTED
の違いについては、Aurora MySQL の分離レベル を参照してください。
大きなトランザクションが終了した後、テーブルの統計情報は古くなっている可能性があります。このような古くなった統計では、Aurora が正確に行数を見積もるには、ANALYZE TABLE
ステートメントが必要になることがあります。大規模な DML ステートメントでは、テーブルデータのかなりの部分がバッファプールに持ち込まれる可能性があります。このデータをバッファプールに入れると、データがプールから削除されるまで、パラレルクエリの選択頻度が低くなります。
セッションが長時間実行トランザクション (デフォルトでは 10 分) 内にある場合、そのセッション内の以降のクエリはパラレルクエリを使用しません。1 つの長期実行クエリ中にもタイムアウトが発生する可能性があります。このタイプのタイムアウトは、パラレルクエリ処理がスタートされるまでの最大間隔 (現在は 10 分) より長くクエリが実行された場合に発生する可能性があります。
autocommit=1
セッションに mysql
を設定して、偶発的に長時間実行トランザクションがスタートされる機会を減らすことができます。テーブルに対する SELECT
ステートメントでさえ、読み取りビューを作成してトランザクションをスタートします。読み取りビューは、トランザクションがコミットされるまで続くクエリ用の一貫したデータセットです。このようなアプリケーションは autocommit
設定をオフにして実行する可能性があるため、Aurora で JDBC または ODBC アプリケーションを使用する場合にもこの制限に注意してください。
次の例は、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 ツリーインデックス
ANALYZE TABLE
ステートメントによって収集される統計は、各列のデータの特性に基づいて、パラレルクエリまたはインデックスのルックアップをいつ使用するかをオプティマイザが決定するのに役立ちます。テーブル内のデータを大幅に変更する DML 操作の後で ANALYZE TABLE
を実行することにより、統計情報を最新の状態に保ちます。
インデックスのルックアップがデータ集約型スキャンなしで効率的にクエリを実行できる場合は、Aurora は インデックスのルックアップを使用する可能性があります。そうすることにより、パラレルクエリ処理のオーバーヘッドが回避されます。また、どの Aurora DB クラスターでも同時に実行できるパラレルクエリの数には同時実行制限があります。テーブルのインデックス付けにベストプラクティスを使用して、最も頻繁で最も並行性の高いクエリがインデックスのルックアップを使用するようにしてください。
全文検索 (FTS) インデックス
現在のところ、全文検索インデックスを含むテーブルでは、クエリで全文検索インデックスのある列を参照しているか MATCH
演算子を使用しているかどうかにかかわらず、パラレルクエリは使用されません。
仮想列
現在のところ、仮想列を含むテーブルでは、クエリで仮想列を参照しているかどうかにかかわらず、パラレルクエリは使用されません。
組み込みキャッシュメカニズム
Aurora には、組み込みキャッシュメカニズム、つまりバッファプールとクエリキャッシュが組み込まれています。Aurora オプティマイザは、どのクエリが特定のクエリに対して最も効果的かに応じて、これらのキャッシュメカニズムとパラレルクエリを選択します。
パラレルクエリが行をフィルタリングし、列の値を変換して抽出すると、データはデータページではなくタプルとしてヘッドノードに返されます。したがって、パラレルクエリを実行しても、バッファプールにはページが追加されず、既にバッファプールにあるページは削除されます。
Aurora は、バッファプール内に存在するテーブルデータのページ数と、その番号が表すテーブルデータの割合を検証します。Aurora はその情報を使用して、パラレルクエリを使用する方が効率的かどうかを判断します (また、バッファプール内のデータをバイパスします)。または、Aurora はバッファプールにキャッシュされたデータを使用する非パラレルクエリ処理パスを使用することがあります。キャッシュされるページと、データ集約型のクエリがキャッシュおよび削除に与える影響は、バッファプールに関連する構成設定によって異なります。したがって、バッファプール内の常に変化するデータに依存するため、特定のクエリでパラレルクエリが使用されているかどうかを予測することは困難です。
また、Aurora はパラレルクエリに同時実行制限を課します。すべてのクエリがパラレルクエリを使用するわけではないので、複数のクエリによって同時にアクセスされるテーブルは、通常、バッファプール内のデータのかなりの部分を占めます。したがって、Aurora はパラレルクエリに対してこれらのテーブルを選択しないことがよくあります。
同じテーブルで非パラレルクエリのシーケンスを実行すると、データがバッファプールにないため、初期のクエリが遅くなる可能性があります。これでバッファプールが「ウォームアップ」状態になるため、2 番目以降のクエリは非常に高速になります。パラレルクエリは、通常、テーブルに対する初期のクエリからの一貫したパフォーマンスを示します。パフォーマンステストを実行するときは、コールドバッファプールとウォームバッファプールの両方を使用して、非パラレルクエリを評価します。場合によっては、ウォームバッファプールを使用した結果は、パラレルクエリ時間とよく比較できます。その場合、そのテーブルに対するクエリの頻度などの要因を考慮してください。また、そのテーブルのデータをバッファプールに保持するメリットがあるかどうかも考慮してください。
クエリキャッシュは、同じクエリが送信されたときに基になるテーブルのデータに変更がない場合に、クエリがもう一度実行されることを防ぎます。パラレルクエリ機能によって最適化されたクエリは、クエリキャッシュに入り、効果的に再度実行することができます。
注記
パフォーマンスの比較を行うとき、クエリキャッシュは意図的に低いタイミング数を生成する可能性があります。したがって、ベンチマークのような状況では、sql_no_cache
ヒントを使用できます。このヒントは、以前に同じクエリが実行された場合でも、クエリキャッシュから結果が提供されるのを防ぎます。ヒントは、クエリの SELECT
ステートメントの直後に表示されます。このトピック内のパラレルクエリ例の多くにはこのヒントが含まれているので、パラレルクエリで有効化されているクエリとそうでないクエリのバージョン間で、クエリ時間を比較できます。
パラレルクエリの本稼働使用に移行するときは、出典からこのヒントを削除するようにしてください。
オプティマイザヒント
オプティマイザを制御するもう 1 つの方法は、オプティマイザヒントを使用することです。オプティマイザヒントは個々のステートメント内で指定できます。例えば、ステートメント内の 1 つのテーブルの最適化を有効にして、別のテーブルの最適化を無効にすることができます。これらのヒントの詳細については、MySQL リファレンスマニュアルの「オプティマイザヒント
Aurora MySQL クエリで SQL ヒントを使用して、パフォーマンスを微調整できます。ヒントを使用して、重要なクエリの実行計画が予測不可能な条件のために変更されないようにすることもできます。
SQL ヒント機能を拡張して、クエリプランのオプティマイザの選択を制御できるようにしました。これらのヒントは、パラレルクエリ最適化を使用するクエリに適用されます。詳細については、「Aurora MySQL のヒント」を参照してください。
MyISAM テンポラリテーブル
パラレルクエリの最適化は、InnoDB テーブルにのみ適用されます。Aurora MySQL はテンポラリテーブルの背後で MyISAM を使用するため、テンポラリテーブルを含む内部クエリフェーズではパラレルクエリは使用されません。これらのクエリフェーズは、Using
temporary
出力に EXPLAIN
によって示されています。