すべてのプロダクト
Search
ドキュメントセンター

PolarDB:EXPLAINステートメントを実行して弾性並列クエリ実行プランを表示する

最終更新日:Jun 04, 2024

このトピックでは、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_typeDEPENDENTサブクエリで、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_typesubqueryで、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キーワードが含まれている場合、並列クエリが使用されているときのさまざまなコンピューティングタスクの実行時間を表示できます。 並列クエリの場合、複数のワーカーの中の各オペレーターの最大、最小、および平均計算時間を含む、各オペレーターの各ワーカーの計算時間も記録されます。