このトピックでは、PolarDB-X 1.0のSQLエグゼキュータが、プッシュダウンできない構造化クエリ言語 (SQL) パーツを実行する方法について説明します。
基本概念
SQL executorは、PolarDB-X 1.0の論理層で演算子を実行するコンポーネントです。 ポイントクエリ用の単純なSQL文は、多くの場合、実行のためにストレージ層MySQLに完全にプッシュダウンされます。 したがって、あなたはエグゼキュータの存在を認識していません。 MySQLの結果は、デコードおよびエンコードされた後にユーザーに送信されます。 ただし、複雑なSQLステートメントの演算子をすべてプッシュダウンすることはできません。 この場合、プッシュダウンできない計算を実行するには、PolarDB-X 1.0 executorが必要です。
次のクエリSQL文を例として使用します。
SELECT l_orderkey, sum(l_extendedprice *(1 - l_discount)) AS収益
顧客、注文、LINEITEMから
c_mktsegment = 'AUTOMOBILE'
とc_custkey = o_custkey
とl_orderkey = o_orderkey
およびo_orderdate <''1995-03-13'
およびl_shipdate > '1995-03-13'
グループBY l_orderkey;
EXPLAIN
コマンドを実行して、PolarDB-X 1.0の実行プランを表示します。
HashAgg(group="l_orderkey", revenue="SUM(*)")
HashJoin(condition="o_custkey = c_custkey", type="inner")
収集 (concurrent=true)
LogicalView(tables="ORDERS_[0-7],LINEITEM_[0-7]", shardCount=8, sql="SELECT 'ORDERS'.'o_custkey', 'LINEITEM'.'l_orderkey', ('LINEITEM'.'l_extendedprice' *? -'LINEITEM'.'l_discount') AS 'x' FROM 'ORDERS' AS 'ORDERS' INNER JOIN 'LINEITEM' AS 'LINEITEM' ON ((('ORDERS'.'o_orderkey' = 'LINEITEM'.'_) 'LINEIDE.'?'__(')' ('ORRRSDEIRDEIDEIDEIDEIDERS') ')'? '?'_(''__) ''
収集 (concurrent=true)
LogicalView(tables="CUSTOMER_[0-7]" 、shardCount=8、sql="SELECT 'c_custkey' FROM 'CUSTOMER' AS 'CUSTOMER' WHERE ('c_mktsegment' = ?)")
次の図では、SQL文が実行されると、LogicalView
のSQL文がMySQLに配信されます。 プッシュダウンできない部品 (LogicalView
以外の演算子) は、PolarDB-X 1.0エグゼキュータによって計算されます。 このようにして、ユーザーのSQLステートメントの必要な最終結果が取得されます。

火山モデル
多くのデータベースと同様に、PolarDB-X 1.0はVolcanoモデルを採用しています。 open()
やnext()
などのAPI操作は、すべての演算子に対して定義されます。 演算子は、実行計画に基づいて演算子ツリーを形成します。 上位層演算子は、下位層演算子のnext()
演算の出力結果を呼び出すことによって計算される。 最終的に、最上層のオペレータは、ユーザのために所望の結果を生成し、その結果をクライアントに返す。
次の例では、HashJoin
演算子がハッシュテーブルを作成したとします。 上位層のProject演算子がデータを要求すると、HashJoin
はまず下位層のGather
演算子にデータのバッチを要求します。 次に、HashJoinがテーブルを参照してJOIN結果を取得し、その結果をProjectオペレータに返します。

場合によっては、オペレータは、すべてのデータを読み取り、データをメモリにキャッシュする必要がある。 このプロセスは具体化と呼ばれます。 たとえば、HashJoin演算子は、内部テーブルからすべてのデータを読み取り、メモリ内にハッシュテーブルを作成する必要があります。 他の同様の演算子には、HashAgg (集約) とMemSort (ソート) が含まれます。
メモリリソースは限られています。 したがって、マテリアライズドデータの量が1つのクエリの制限を超える場合、または使用されるメモリの合計がPolarDB-X 1.0ノードのメモリ制限を超える場合、メモリ不足エラー (OUT_OF_memory
) が報告されます。
並列クエリ
並列クエリとは、複数のスレッドを使用して並列に実行される複雑なクエリを指します。
並列クエリの実行プランは、元の実行プランと比較して変更されます。 上記のクエリも例として使用されます。 次の例は、上記のクエリの並列実行プランを示しています。
Gather(parallel=true)
ParallelHashAgg(group="o_orderdate,o_shippriority,l_orderkey", revenue="SUM(*)")
ParallelHashJoin(condition="o_custkey = c_custkey", type="inner")
LogicalView(tables="ORDERS_[0-7],LINEITEM_[0-7]", shardCount=8, sql="SELECT 'ORDERS'.'o_custkey ', 'ORDERS'.'o_orderdate', 'ORDERS'.'o_shippriority', ''LINE_key'.' ('''._. ') -'LINEITEM'.'l_discount') AS 'x' FROM 'ORDERS' AS 'ORDERS' INNER JOIN 'LINEITEM' AS 'LINEITEM' ON (((('ORDERS'.'o_orderkey'='LINETEM'. '_ parallel) ') AND ('ORERSDER'''_orderkey'>'? '?'? ')', ''m'
LogicalView(tables="CUSTOMER_[0-7]" 、shardCount=8、sql="SELECT 'c_custkey' FROM 'CUSTOMER' WHERE ('c_mktsegment' = ?)" 、parallel=true)

Gather演算子が並列実行プランの上位層にプルアップされていることがわかります。 これは、Gather演算子の下のすべての演算子が並列に実行され、Gather演算子に達するまで集約できることを示します。
以下の演算子Gatherは、実行中に複数の実行インスタンスにインスタンス化されます。 各インスタンスは、並列度 (DOP) に対応する。 デフォルトでは、DOPは1つのサーバー上のコア数に等しくなります。 Standard EditionインスタンスのデフォルトのDOPは8です。 Enterprise EditionインスタンスのデフォルトのDOPは16です。
実行プロセスの診断分析
前のセクションで説明したEXPLAIN命令に加えて、次の命令はパフォーマンスの問題を分析するのに役立ちます。
EXPLAIN ANALYZE
命令は、PolarDB-X 1.0サーバー内の各演算子の実行パフォーマンスメトリックを分析します。EXPLAIN EXECUTE
命令は、結果が集計された後にMySQLのEXPLAIN結果を返します。
次のセクションでは、前のセクションで説明したクエリを例として使用して、クエリのパフォーマンスの問題を分析する方法を説明します。
EXPLAIN ANALYZE
が実行された後、次の結果 (一部の無関係な情報が削除されました) が得られます。
の分析を説明してください選択l_orderkey、sum(l_extendedprice *(1 - l_discount)) は、CUSTOMER、ORDERS、LINEITEMからの収益です。c_mktsegment = 'AUTOMOBILE' 、c_custkey = o_custkey、lderkey=o_custkey-13 ';' by 1995-''''''''''''- 03; ''''''-order_order_order_
HashAgg(group="o_orderdate,o_shippriority,l_orderkey", revenue="SUM(*)")
... 実時間=23.916 + 0.000、実行カウント=11479、実メモリ=1048576、インスタンス=1...
HashJoin(condition="o_custkey = c_custkey", type="inner")
... 実時間=0.290 + 23.584、実行カウント=30266、実メモリ=1048576、インスタンス=1...
収集 (concurrent=true)
... 実時間=0.000 + 23.556、実行カウント=151186、実メモリ=0、インスタンス=1...
LogicalView(tables="ORDERS_[0-7],LINEITEM_[0-7]", shardCount=8, sql="SELECT 'ORDERS'.'o_custkey ', 'ORDERS'.'o_orderdate', 'ORDERS'.'o_shippriority', ''LINE_key'.' ('''._. ') -'LINEITEM'.'l_discount') AS 'x' FROM 'ORDERS' AS 'ORDERS' INNER JOIN 'LINEITEM' AS 'LINEITEM' ON ((('ORDERS'.'o_orderkey' = 'LINEITEM'.'_) 'LINEIDE.'?'__(')' ('ORRRSDEIRDEIDEIDEIDEIDERS') ')'? '?'_(''__) ''
... 実時間=0.000 + 23.556、実行カウント=151186、実メモリ=0、インスタンス=4...
収集 (concurrent=true)
... 実時間=0.000 + 0.282、実行カウント=29752、実メモリ=0、インスタンス=1...
LogicalView(tables="CUSTOMER_[0-7]", shardCount=8, sql="SELECT 'c_custkey' FROM 'CUSTOMER' AS 'CUSTOMER' WHERE ('c_mktsegment' = ?)")
... 実時間=0.000 + 0.282、実行カウント=29752、実メモリ=0、インスタンス=4...
表示の説明です。
- actual time: 子演算子によって消費された時間を含む、実際の実行時間を示します。 プラス記号 (+) の左側の値は、open操作によって消費される時間を示します。 オープン操作は、データを準備するために使用される。 プラス記号 (+) の右側の値は、次の操作で消費される時間を示します。 次の操作は、データを生成するために使用される。
- actual rowcount: 出力行の数を示します。
- actual memory: 演算子が使用するメモリスペースのサイズを示します。 単位:byte。
- instances: インスタンスの数を示します。 並列クエリではないクエリの場合、値は常に1です。 並列演算子の場合、各DOPはインスタンスに対応します。 インスタンス数が1に等しくない場合、実際の時間パラメーターは、複数のインスタンスを並行して実行することによって消費される実際の合計時間を示します。 実際のrowcountパラメーターは、複数のインスタンスが並列に実行されたときの出力行の総数を示します。 実際のメモリパラメータは、複数のインスタンスが並列で実行されるときに使用されるメモリの合計サイズを示します。
実時間=20、インスタンス=8
は、この演算子に対して8つのインスタンスが並列に実行され、平均実行時間が2.5秒であることを示します。上記の出力は例として使用され、次のように解釈されます。
- HashAgg演算子のopen操作では、下位層のHashJoinとグループの出力を取得し、すべての出力データを集約するのに23.916秒かかります。 具体的には、下位層の出力を取得するのに23.601秒かかり、データをグループ化して集約するのに約0.3秒しかかかりません。
- HashJoin演算子のopen操作では、右側のテーブルからデータを取り出し (下の位置に収集) 、ハッシュテーブルを作成するのに0.290秒かかります。 次の操作で左側のテーブルからデータを取得し、ハッシュテーブルにクエリを実行してJOIN結果を取得するには23.584秒かかります。
- Gather演算子は、複数の結果セットを収集するためにのみ使用されます。 一般的に、コストは低いです。
- 左 (上の位置) のLogicalView演算子からデータをプルするのに23.556秒かかります。 この演算子がクエリのパフォーマンスのボトルネックであると判断できます。
- 右 (下の位置) のLogicalView演算子からデータをプルするのに0.282秒かかります。
結論として、パフォーマンスのボトルネックは左側のLogicalView演算子にあります。 この演算子がORDERSでJOINクエリを実行し、LINEITEMとMySQLが実行計画に基づいてこのクエリを低速で実行していることがわかります。
MySQL EXPLAINの結果を表示するには、次のEXPLAIN EXECUTE
ステートメントを実行します。

上の図では、赤いボックスは左側のLogicalViewのプッシュダウンクエリに対応し、青いボックスは右側のLogicalViewのプッシュダウンクエリに対応しています。