web-dev-qa-db-ja.com

ポリベースの性能

SQL Server外部データソースを使用して、SQL Server 2019(CU2)ボックスでPolybaseを実験しており、パフォーマンスは良好ではありません。ほとんどの場合、1400%増加しています。いずれの場合も、クエリするすべてのテーブル/ビューは、同じ外部データソースを指す外部テーブルからのものです。ローカルボックスで分割されたクエリを実行することと、外部テーブルとしてプルされたビューとして同じクエリを使用することの両方を試みました。また、リモートサーバーから外部テーブルにすべての統計を変更せずにスクリプト化しました。サンプルクエリを使用して、以下のパフォーマンスの違いを確認できます。

サーバーは同じリソースを使用して同一のリソースをセットアップします。32GBのRAM、8つのvCPU、SSDディスク、その他の実行中のクエリはありません。私は2つの異なるリモートサーバーに対して試みました。1つは最新のSP/CUでSQL Server 2016を実行し、もう1つはCU2を実行する2019ボックスです。サーバーは同じホスト上で実行されているVMであり、あらゆる種類のホストの競合を除外しています。

サンプルクエリ:

SELECT
     StockItem_StockNumber, BlanktypeId, NameHTML, BackgroundStrainName, IsExact, IsConditional
     ,ROW_NUMBER() Over(Partition By StockItem_StockNumber, BlanktypeId Order By pt.Name, p.Name, gptr.Text) as row_num
     ,pt.Name as Level1, p.Name as Level2, gptr.Text as Level3, MGIReference_JNumber
     ,gptr.Type as Level3Type  
FROM
     StockItemBlanktypes sig
     INNER JOIN Blanktypes g on g.BlanktypeId = sig.Blanktype_BlanktypeId
     INNER JOIN BlanktypeStockTerms gpt on gpt.Blanktype_BlanktypeId = g.BlanktypeId
     INNER JOIN StocktypeTerms p on p.StocktypeTermId = gpt.StocktypeTerm_StocktypeTermId
     INNER JOIN BlanktypeStockTermReferences gptr on gptr.BlanktypeStockTerm_BlanktypeStockTermId = gpt.BlanktypeStockTermId
     INNER JOIN StockTermClosures ptc on ptc.ChildStockTerm_StocktypeTermId = p.StocktypeTermId
     INNER JOIN StocktypeTerms pt on pt.StocktypeTermId = ptc.ParentStockTerm_StocktypeTermId
WHERE
     ptc.ParentHeaderKey = 3

リモートの2016/2019ボックスで直接実行:

 SQL Server Execution Times:
   CPU time = 3486 ms,  elapsed time = 5035 ms.

2019ボックスでPolybaseとPUSHDOWN OFFを実行:

 SQL Server Execution Times:
   CPU time = 15016 ms,  elapsed time = 92113 ms.

2019ボックスで、PolybaseとPUSHDOWN ONを使用して実行します。

 SQL Server Execution Times:
   CPU time = 3875 ms,  elapsed time = 74149 ms.

Polybase実行プラン(PUSHDOWNオプションに関係なく同じように見えます):

Polybase Execution Plan

polybaseクエリを開始した直後のsp_whoisactive(待機情報):

wait info

sp_whoisactive(待機情報)をPolybaseクエリに追加します。

more wait info

Polybaseの代わりにリンクサーバーを使用する:

 SQL Server Execution Times:
   CPU time = 3032 ms,  elapsed time = 9316 ms.

これは、クエリの実行にかかる時間のおよそ1400%の増加です。混乱しているのは、MicrosoftがETLの代替としてPolybaseを推進していることですが、この種のパフォーマンスでこれを実現する方法はありません。

他の人々は、SQL ServerからSQL Serverへの接続でPolybaseを使用して同様のパフォーマンスを見ていますか?そして、ポリベースの内部操作がこの種の遅延を引き起こしている可能性があることを誰かが知っていますか?

ありがとうございました。


2020年2月23日更新:

クエリのパフォーマンスに影響があるわけではありませんが、今日、PolybaseクエリがMAXDOP設定(インスタンス全体またはクエリヒント)を順守しておらず、設定された統計CPU時間が正確に報告していないことを発見しました。

XMLで実行計画を確認できましたが、これが唯一の有益なセクションです。 PREEMPTIVE_SHAREDMEM_GETDATAで見つけられる唯一の情報は、COMオブジェクトのGetDataメソッドの呼び出しが完了するのをスレッドが待っているときの待機タイプです。

enter image description here


2020年2月23日の2回目の更新:

1つの大きなテーブルを作成し、ローカルとPolybaseの両方で「select *」を実行しました。これらの実行時間はほとんど同じです。私はマイクロソフトとサポートケースを開きました。何か進展があった場合は報告します。


2020年2月24日に更新:

Kevinの応答(下記)の後、明確にするために元の投稿にいくつかの微調整を加え、彼が参照したクエリ/ DMVを実行すると、次の結果が返されます。

enter image description here

4
Select 'DBA'

上記のクエリにリストされているすべてのテーブルは、同じ外部データソースを指す外部テーブルであるという前提から作業します。このことを念頭に置いて、いくつかの考慮事項があります。

分散リクエスト

現在持っているものより少し多くの情報を提供する2つのDMVがあります:_sys.dm_exec_distributed_requests_と_sys.dm_exec_distributed_request_steps_。遅いクエリを実行して、分散リクエストDMVに何が表示されるかを確認してください。この目的で使用するサンプルクエリを次に示します。

_SELECT TOP(100)
    r.execution_id,
    r.status,
    r.error_id,
    r.start_time,
    r.end_time,
    r.total_elapsed_time,
    t.text
FROM sys.dm_exec_distributed_requests r
    CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
ORDER BY
    r.end_time DESC;
GO
_

次のような複数の結果が表示される場合があります。

A single T-SQL SELECT statement generates two separate PolyBase operations.

これらのそれぞれについて、関連する一連のステップを取得できます(実行IDが何であっても使用するようにクエリを変更します)。

_SELECT
    rs.execution_id,
    rs.step_index,
    rs.operation_type,
    rs.distribution_type,
    rs.location_type,
    rs.[status],
    rs.error_id,
    rs.start_time,
    rs.end_time,
    rs.total_elapsed_time,
    rs.row_count,
    rs.command
FROM sys.dm_exec_distributed_request_steps rs
WHERE rs.execution_id IN ('QID573', 'QID574')
ORDER BY
    rs.execution_id DESC,
    rs.step_index ASC;
GO
_

私が探す傾向があるのは、「過剰な」行数です。たとえば、少ない行数が返されることを期待しているが、特定のステップの行数がはるかに多い場合、PolyBaseデータ移動サービスは、理想的な数よりも多くの行を送信し、PolyBaseエンジンに強制的にテーブルを組み合わせるという汚い仕事をする。それが次の考慮事項につながります。

フィルターと述語

クエリでは、明示的なフィルターや述語は表示されませんが、暗黙的なフィルターがあるかどうかはわかりません。たとえば、StocktypeTermsテーブルでは、結合条件に_ParentHeaderKey = 3_が表示されます。これが非常に選択的な結合基準である場合、PolyBaseがすべての行をストリーミングしてから、フィルター操作をリモートで実行して必要な行だけを取得するのではなく、ローカル側でフィルターを実行している可能性があります。

これが当てはまる理由はいくつかあります。たとえば、複雑なフィルター(そうである可能性があります)、PolyBaseがプッシュダウンできない述語(プッシュダウンに使用できるものにいくつかの厳しい制限があります)、または2つの異なる外部から形成される述語データソース(これは私が見たいシナリオですが、今日はうまく機能しません)。 WHERE句がないため、このセクションではこれ以上詳しく説明しません。

ネットワーク性能

外部データソースとローカルSQLサーバーインスタンスの間にネットワークの問題がある場合、速度が低下する可能性があります。 2番目の更新では、単一のテーブルに対して外部テーブルを作成し、そのすべてのデータをダウンストリームすること、およびタイミングの違いはわずかであることを言及しました。これは、ネットワーク速度があなたのケースでは重要な問題ではないことを示しています。

特定のガイダンス

上記を念頭に置いて、何が問題であるかを理解する方法として、私はあなたの特定のシナリオに私がお勧めするものです。

実行プランに示されている313,585よりも多くの行がローカルSQL Serverインスタンスに送信されている場合は、リモートで処理できるローカルSQL Serverインスタンスで余分な作業が発生していることを意味します。役立つ可能性のあるものが2つあります。

まず、OPTION(FORCE EXTERNALPUSHDOWN)をオンにしてクエリを実行してみます。 (外部データソース定義で_PUSHDOWN = ON_と_PUSHDOWN = OFF_を設定して)述語プッシュダウンを有効または無効にすることについて説明しましたが、このヒントを指定したかどうかは明確ではありませんでした。ゼロ以外の確率で、これにより、PolyBaseエンジンの動作が、クエリを記述するだけで表示される動作とは異なるものになる可能性があります。あなたの特定のクエリを考えると、このクエリのヒントは違いをもたらさないと私は推測しています。

次に、リモートデータソースで上記のSQLクエリを使用してビューを作成します。次に、そのリモートビューを参照する外部テーブルをローカルに作成します。これにより、ローカルSQL Serverに何かを送信する前に、外部データソースがこれらすべてのテーブルを結合する作業を強制されます。

私の単純なケースでは、クエリのビューを作成すると、分散リクエストが減り、データの取得時間が短縮されました。

Querying an external table pointing to a view.

4
Kevin Feasel