このトピックでは、EXPLAINステートメントを実行して、実行計画のエラスティック並列クエリ情報を表示する方法について説明します。
テーブルの例
次の例では、pq_test
テーブルを使用して並列クエリをテストします。
スキーマ:
SHOW CREATE TABLE pq_test\G *************************** 1。 行 *************************** テーブル: pq_test テーブルの作成: Create Table 'pq_test' ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `help_topic_id` INT(10) UNSIGNED NOT NULL, `name` CHAR(64) NOT NULL, `help_category_id` SMALLINT(5) UNSIGNED NOT NULL, `description` TEXT NOT NULL, `example` TEXT NOT NULL, `url` TEXT NOT NULL, 主要なキー ('id') ) エンジン=InnoDB AUTO_INCREMENT=21495809デフォルト料金=utf8 1行セット (0.00秒)
テーブルのサイズ:
SHOW TABLE STATUS\G *************************** 1。 行 *************************** Name: pq_test Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 20064988 Avg_row_length: 1898 Data_length: 38085328896 Max_data_length: 0 Index_length: 0 Data_free: 4194304 Auto_increment: 21495809 Create_time: 2019-07-30 01:35:27 Update_time: NULL Check_time: NULL Collation: utf8_general_ci Checksum: NULL Create_options: コメント: 1行セット (0.02秒)
SQL ステートメント :
SELECT COUNT(*) FROM pq_test;
EXPLAINステートメント
非並列クエリの表示
EXPLAINステートメントは、非並列クエリで使用できます。
例:
SET max_parallel_degree=0; EXPLAIN SELECT COUNT(*) FROM pq_test\G
サンプル結果:
*************************** 1。 行 ***************************
Id: 1
Select_type: SIMPLE
Table: pq_test
Partitions: NULL
タイプ: index
Possible_keys: NULL
Key: PRIMARY
Key_len: 8
Ref: NULL
Rows: 20064988
Filtered: 100.00
エクストラ: インデックスの使用
セットの1列、1警告 (0.03秒)
並列クエリの表示
PolarDB for MySQL 8.0.1では、並列クエリでEXPLAINステートメントを使用できます。
例:
EXPLAIN SELECT COUNT(*) FROM pq_test\G
サンプル結果:
*************************** 1。 行 *************************** Id: 1 Select_type: SIMPLE Table: <gather2> Partitions: NULL タイプ: すべて Possible_keys: NULL Key: NULL Key_len: NULL Ref: NULL Rows: 20064988 Filtered: 100.00 エクストラ: NULL *************************** 2. 行 *************************** Id: 2 Select_type: SIMPLE Table: pq_test Partitions: NULL タイプ: index Possible_keys: NULL Key: PRIMARY Key_len: 8 Ref: NULL Rows: 10032494 Filtered: 100.00 エクストラ: パラレルスキャン (2ワーカー); インデックスの使用 セットの2列、1警告 (0.00秒)
PolarDB for MySQL 8.0.2では、並列クエリで
EXPLAIN FORMAT=TREE
ステートメントを使用できます。 これは、クエリ処理のより正確な説明を返します。例:
EXPLAIN FORMAT=TREE SELECT COUNT(*) FROM pq_test\G
サンプル結果:
*************************** 1。 行 *************************** 説明: -> ギャザー内の行をカウント (コスト=... 行=1) -> 収集 (スライス: 1; ワーカー: 2、ノード: 2) -> PRIMARYを使用したpq_testの並列インデックススキャン、並列パーティション: 8 (コスト=... 行=20064988)
結果は次の情報を示します。
EXPLAIN出力は、並列プランにGather操作が含まれていることを示します。 収集は、すべてのワーカーによって生成される部分的な結果を収集するために実装されます。
さらに、Extraフィールドの情報は、4つのワーカーを使用して
pq_test
テーブルに対して並列スキャンが実行されることを示しています。使用されたワーカーの数とノードの数は、Gather操作で表示されます。 合計2つのノードが使用され、各ノードには2つのワーカーがあります。
サブクエリを含む並列クエリの表示
PolarDB for MySQL 8.0.1では、サブクエリを含む並列クエリでEXPLAINステートメントを使用できます。
例:
EXPLAIN SELECT o_orderpriority, COUNT(*) as order_count から 注文 どこ o_orderdate >= '1994-04-01' AND o_orderdate < date_add('1994-04-01 '、インターバル '3' 月) ANDが存在する ( SELECT * FROM lineitem WHERE l_orderkey = o_orderkey and l_commitdate < l_receiptdate ) グループ化 o_orderpriority 注文によって o_orderpriority\G
サンプル結果:
*************************** 1。 行 *************************** id: 1 select_type: PRIMARY テーブル: <gather1.1> パーティション: NULL タイプ: すべて possible_keys: NULL キー: NULL key_len: NULL ref: NULL 行: 1489068 filtered: 100.00 追加: 一時的な使用。filesortの使用 *************************** 2. 行 *************************** id: 1 select_type: PRIMARY テーブル: 注文 パーティション: NULL タイプ: 範囲 possible_keys: i_o_orderdate キー: i_o_orderdate key_len: 3 ref: NULL 行: 568369 filtered: 100.00 追加: パラレルスキャン (2ワーカー); インデックス条件の使用; どこを使用; 一時的な使用 3. 行 *************************** id: 2 select_type: 従属サブクエリ テーブル: lineitem パーティション: NULL タイプ: ref possible_keys: PRIMARY,i_l_orderkey キー: PRIMARY key_len: 4 ref: tpch_10.orders.O_ORDERKEY 行: 4 filtered: 33.3 エクストラ: パラレルプッシュダウン; どこを使用 セットの3列、2警告 (0.01秒)
上記の結果では、サブクエリの
select_type
はDEPENDENTサブクエリ
で、Extra
フィールドはParallel pushdown
に設定されています。これは、サブクエリが並列処理のためにワーカーに送信されることを示しています。PolarDB for MySQL 8.0.2では、サブクエリを含む並列クエリで
FORMAT=TREE
ステートメントを使用できます。 これは、クエリ処理のより正確な説明を返します。例 1
例:
EXPLAIN FORMAT=TREE SELECT o_orderpriority, COUNT(*) as order_count から 注文 どこ o_orderdate >= '1994-04-01' AND o_orderdate < date_add('1994-04-01 '、インターバル '3' 月) ANDが存在する ( SELECT * FROM lineitem WHERE l_orderkey = o_orderkey and l_commitdate < l_receiptdate ) グループ化 o_orderpriority 注文によって o_orderpriority\G
サンプル結果:
*************************** 1。 行 *************************** EXPLAIN: -> 並べ替え: <temporary>.o_orderpriority -> <temporary> のテーブルスキャン -> 一時テーブルを使用した集計 (コスト=1746887.76行=1489068) -> 収集 (スライス: 1; ワーカー: 2) (コスト=1597980.96行=1489068) -> <temporary> のテーブルスキャン -> 一時テーブルを使用した集計 (コスト=1486290.85行=744534) -> フィルター: 存在します (選択 #2) (コスト=772982.43行=568369) -> i_o_orderdateを使用した注文の並列インデックス範囲スキャン、インデックス条件 :( (orders.O_ORDERDATE >= DATE'1994-04-01 ') および (orders.O_ORDERDATE < < <cache>(('1994-04-01' + interval '3' month)))) 、並列パーティション: 89 (コスト=772982.43行=568369) -> 選択 #2 (条件のサブクエリ; 依存) -> 制限: 1行 (s) -> フィルター :( lineitem.L_COMMITDATE < lineitem.L_RECEIPTDATE) (コスト=1.14行=1) -> PRIMARYを使用したlineitemのインデックスルックアップ (L_ORDERKEY=orders.O_ORDERKEY) (コスト=1.14行=4) セットの1列、1警告 (0.02秒)
例 2
例:
EXPLAINフォーマット=ツリー 選択 ps_partkey, 値としての合計 (ps_supplycost * ps_availqty) から partsupp, サプライヤー, 国家 ここで ps_suppkey = s_suppkey およびs_nationkey = n_nationkey およびn_name = 'IRAN' グループによって ps_partkeyを持つ sum(ps_supplycost * ps_availqty) > ( 選択 sum(ps_supplycost * ps_availqty) * 0.0000010000 から partsupp, サプライヤー, 国家 ここで ps_suppkey = s_suppkey およびs_nationkey = n_nationkey およびn_name = 'IRAN' ) による注文 値descリミット1;
サンプル結果:
| -> 制限: 1行 (コスト=1408498.03行=1) -> 収集 (マージソート; スライス: 1; ワーカー: 256; 実際のワーカー: 32) (コスト=1408498.03行=256) -> 制限: 1行 (コスト=1408404.20行=1) -> 並べ替え: <temporary>.value DESC、入力をチャンクごとに1行に制限します (コスト=1408404.20行=803182) -> フィルター :( sum(((partsupp.PS_SUPPLYCOST * partsupp.PS_AVAILQTY)) > (select #2)) -> <temporary> のテーブルスキャン -> 一時テーブルを使用した集計 (コスト=1408404.20行=803182) -> 内部ハッシュ結合 (partsupp.PS_SUPPKEY = supplier.S_SUPPKEY) (コスト=829770.18行=327820) -> 並列パーティションを使用したpartsuppでの並列テーブルスキャン: 2882、partition_keys: 1 (コスト=6347528.15行=3176912) -> ハッシュ -> ブロードキャスト (スライス: 2; ワーカー: 256; ノード: 16) (コスト=103382.56行=1029632) -> ネストされたループ内部結合 (コスト=409.36行=4022) -> フィルター :( nation.N_NAME = 'IRAN') (コスト=2.29行=3) -> 国のテーブルスキャン (コスト=2.29行=25) -> SUPPLIER_FK1 (S_NATIONKEY=nation.N_NATIONKEY) を使用したサプライヤでの並列インデックス検索、並列パーティション: 9243 (コスト=65.94行=1609) -> 選択 #2 (条件内のサブクエリ; 一度だけ実行; 共有アクセス) -> 集計: sum('<collector>'.tmp_field_0) (コスト=825576.85行=1) -> 収集 (スライス: 1; ワーカー: 256; ノード: 16) (コスト=825564.05行=256) -> 集計: 合計 ((partsupp.PS_SUPPLYCOST * partsupp.PS_AVAILQTY)) (コスト=825541.20行=1) -> 内部ハッシュ結合 (partsupp.PS_SUPPKEY = supplier.S_SUPPKEY) (コスト=809150.20行=327820) -> 並列パーティションを使用したpartsuppでの並列テーブルスキャン: 14405 (コスト=6147699.35行=3176912) -> ハッシュ -> ブロードキャスト (スライス: 2; ワーカー: 256; ノード: 16) (コスト=103382.56行=1029632) -> ネストされたループ内部結合 (コスト=409.36行=4022) -> フィルター :( nation.N_NAME = 'IRAN') (コスト=2.29行=3) -> 国のテーブルスキャン (コスト=2.29行=25) -> SUPPLIER_FK1 (S_NATIONKEY=nation.N_NATIONKEY) を使用したサプライヤでの並列インデックス検索、並列パーティション: 9243 (コスト=65.94行=1609)
上記の結果では、サブクエリの
select_type
はsubquery
で、Select #2
フィールドはShared access
に設定されています。 PolarDBオプティマイザは事前に並列サブクエリを実行し、結果はワーカー間で共有されます。 このクエリプランでは、サブクエリの外層のクエリブロックは、ポリシーの制限により、マルチノードelastic parallelクエリを実行できません。 外部クエリの複数の並列ワーカーは、クエリが配信されるノード内で単一ノードのエラスティック並列クエリを実行できます。
さまざまなコンピューティングタスクの実行時間の表示
PolarDB for MySQL 8.0.2では、EXPLAIN ANALYZE
ステートメントを実行して、並列クエリを使用する場合のさまざまなコンピューティングタスクの実行時間を表示できます。
例:
EXPLAIN解析select c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice、 sum(l_quantity) から 顧客、 注文、 lineitem ここで o_orderkey in ( 選択 l_orderkey から lineitem グループによって l_orderkey持っている sum(l_quantity) > 313 ) とc_custkey = o_custkey とo_orderkey = l_orderkey グループによって c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice による注文 o_totalprice desc、 o_orderdate LIMIT 100;
サンプル結果:
| -> 制限: 100行 (コスト=14.62行=1) (実際の時間=1.252 .. 1.252行=0ループ=1) -> 収集 (マージソート; スライス: 1; ワーカー: 1; ノード: 2) (コスト=14.62行=1) (実際の時間=1.250 .. 1.250行=0ループ=1) -> 制限: 100行 (コスト=4.52行=1) (実際の時間=0.084,0.084,0.084 .. 0.084,0.084,0行=0,0、0ループ=1,1、1) -> 並べ替え: <temporary>.O_TOTALPRICE DESC、<temporary>.O_ORDERDATE、入力をチャンクごとに100行に制限する (コスト=4.52行=1) (実際の時間=0.083,0.083,0.083 .. 0.083,0.083,0.083行=0,0、0ループ=1,1、1) -> <temporary> のテーブルスキャン (実際の時間=0.070,0.070,0.070 .. 0.070,0.070,0.070行=0,0、0ループ=1,1、1) -> 一時テーブルを使用した集計 (コスト=4.52行=1) (実際の時間=0.001,0.001,0.001 .. 0.001,0.001,0行=0,0、0ループ=1,1、1) -> ネストされたループ内部結合 (コスト=2.86行=4) (実際の時間=0.039,0.039,0.039 .. 0.039,0.039,0行=0,0,0ループ=1,1,1) -> ネストされたループ内部結合 (コスト=1.45行=1) (実際の時間=0.037,0.037,0.037 .. 0.037,0.037,0行=0,0,0ループ=1,1,1) -> 並列パーティションを持つ顧客の並列テーブルスキャン: 1、partition_keys: 1 (コスト=0.35行=1) (実際の時間=0.036,0.036,0.036 .. 0.036,0.036,0.036行=0,0,0ループ=1,1,1) -> フィルター: <in_optimizer>(orders.O_ORDERKEY、<exists>(select #2)) (コスト=1.10行=1) -> ORDERS_FK1を使用した注文のインデックス検索 (O_CUSTKEY=customer.C_CUSTKEY) (コスト=1.10行=1) -> 選択 #2 (条件のサブクエリ; 依存) -> 制限: 1行 (s) -> フィルター :( (sum(lineitem.L_QUANTITY) > 313) および (<cache>(orders.O_ORDERKEY) = <ref_null_helper>(lineitem.L_ORDERKEY))) -> グループ集計: sum(lineitem.L_QUANTITY) -> PRIMARYを使用したlineitemのインデックススキャン (コスト=41554048.20行=380071042) -> PRIMARYを使用したlineitemのインデックスルックアップ (L_ORDERKEY=orders.O_ORDERKEY) (コスト=1.41行=4)
EXPLAINステートメントにANALYZEキーワードが含まれている場合、並列クエリが使用されているときのさまざまなコンピューティングタスクの実行時間を表示できます。 並列クエリの場合、複数のワーカーの中の各オペレーターの最大、最小、および平均計算時間を含む、各オペレーターの各ワーカーの計算時間も記録されます。