Microsoft Fabric の Lakehouse に対して、ADL Gen2 のショートカットを設定することで、Azure ストレージ上のデータを検索するという方法を昨今の環境ではとることができるようになったかと思います。
T-SQL で検索を行う場合には、マネージドテーブルとしてショートカットを作成することになるかと思いますが、レイクハウス に記載されているように次のような制限があります。
Tables フォルダーでは、最上位レベルでのみショートカットを作成できます。 Tables フォルダーの他のサブディレクトリでは、ショートカットはサポートされません。 ショートカットのターゲットに Delta\Parquet 形式のデータが含まれている場合、レイクハウスはメタデータを自動的に同期し、フォルダーをテーブルとして認識します。
マネージドテーブル (Tables) として、ショートカットを作成する際にはサブディレクトリのサポートが行われていません。
Azure ストレージに出力している Azure リソースの診断情報を検索しようとした場合、診断情報は複数のサブディレクトリから構成されているため、Microsoft Fabric でそのままのディレクトリ構造で検索を行うことは難しく、マネージドテーブルとして認識できるディレクトリ構造に加工をして利用する必要があります。(アンマネージドテーブルとして Files 配下にショートカットを作成して、Spark で検索を行うのであれば Microsoft Fabric でも対応可能です)
Synapse Analytics の Serverless (サーバーレス) SQL プールについては、サブディレクトリが複数の構造でも検索を行うことができ、Azure ストレージに対して、T-SQL で分析を行うという場合には、Serverless SQL プールのほうが容易に活用できるケースがあります。
Synapse Analytics のアーキテクチャについては、Azure Synapse SQL アーキテクチャ に記載されていますが、当ブログで Serverless SQL プールの分散処理について触れたことが無かったため、情報をまとめておきたいと思います。
現状、一番詳細に記載されているのは POLARIS: The Distributed SQL Engine in Azure Synapse になるかと思います。
公式ドキュメントではアーキテクチャの内容と、次のドキュメントが参考になるかと。
- Azure Synapse Analytics サーバーレス SQL プールのパフォーマンス チューニング ガイダンス
- Azure Synapse Analytics のサーバーレス SQL プールのベスト プラクティス
- Azure Synapse Analytics のサーバーレス SQL プールのトラブルシューティング
Contents
Serverless SQL プールのアーキテクチャ
前述のとおりアーキテクチャについては Azure Synapse SQL アーキテクチャ に記載されています。
Servelress SQL Pool もノードとしては、一つのコントロールノードと、複数のコンピュートノードで構成されており、クエリで何台のコンピュートノードが使用されるかについては、自動的に制御が行われ、ユーザーが制御することはできないアーキテクチャとなっています。
処理に対して何台のコンピュートノードが使用されているか
分散処理については、実行するクエリに対して何台のコンピュートノードが使用されているかが重要となります。
Azure ストレージに対しての検索で、何台のコンピュートノードが使用されているかを確認する方法としては、次のような 2 種類が考えられるのではないでしょうか。
- Azure ストレージの診断設定を使用した確認
- Serveless SQL プールの DMV を使用した確認
Azure ストレージの診断設定を使用した確認
Serverless SQL プールで Azure ストレージ上のデータを検索した場合、検索対象となる Azure ストレージで診断設定を実施しておくことで、Serveless SQL プールからのアクセスを確認することができます。
診断設定を実施して、Serverless SQL プールから該当の Azure ストレージのファイルを検索する T-SQL を実行すると、診断ログがから次のような KQL でアクセス状況を取得することができます。
let baseTime = datetime('2024-04-17 08:17:00'); StorageBlobLogs | where TimeGenerated >= baseTime | where UserAgentHeader contains "SQLBLOBACCESS" | extend IPAddress = tostring(split(CallerIpAddress, ":")[0]) | summarize cnt = count(), TotalResponseBodySizeKB = sum(ResponseBodySize) / 1024, TotalDurationMs = sum(DurationMs) by IPAddress | extend avgResponseBodySizeKB = TotalResponseBodySizeKB / cnt | sort by cnt asc, IPAddress asc | extend no = row_number();
実際の実行結果が以下になります。
Serverless SQL プールから実行されたアクセスについては「UserAgentheader」に「SQLBLOBACCESS」が含まれますので、この条件で検索することで、Serverless SQL プールからのアクセスについては判断することができます。
6 台のノードからアクセスが行われているのですが、「10.0.0.16」については、アクセス対象となるファイルのリストやプロパティの取得のような、制御の処理が行われる制御用のノードとなるため、アクセスされているデータについては低くなっています。
実際の処理については、2 行目以降のノードで行われており、これらのノードで実際のデータアクセスが行われています。
現在はアクセス回数だけで集計をしていますが、ファイル名 (Uri) や、操作名 (OperationName) を集計軸として情報の確認を行ってみると、Azure ストレージからデータを取得する際のアクセスの特徴としては次のような内容があるかという分析をすることができます。
- ファイル単位でアクセスするコンピュートノードが異なっており、一つのファイルに対して複数のコンピュートノードがアクセスするということはない
- 一つの大きなファイルを検索するより、複数のファイルを検索したほうが効率が良い
- アクセスされるファイル数 / サイズによって、使用されるコンピュートノード数が変化している傾向がある
- 「OPENROWSET」「ファイルのメタデータ」を使用して、アクセスされるファイルを適切にフィルターすることでアクセス対象が少なくなる
上記の結果では 5 台のコンピュートノードが実際のファイルにアクセスを行っていましたが、ファイル数やサイズによっては 10 台のコンピュートノードから検索が行われているというケースもありました。
Azure ストレージの診断設定のログを使用することで「どのファイルにアクセスが行われているか」「何台のコンピュートノードからアクセスが行われているか」を確認することができ、複数台のコンピュートノードで効率的に処理が行われているかを確認することができます。
Serveless SQL プールの DMV を使用した確認
Serverless SQL プールに Synapse Studio / SSMS 等で接続をしてクエリの実行状況を確認する方法としては次のような内容が一般的ではないでしょうか。
これらの確認方法は、クエリの最終的な処理結果を示したものとなり、Azure ストレージで確認をしたような、何台のコンピュートノードが使用されたのかまでは確認ができないのではないでしょうか。
ドキュメントに公開されていない DMV の利用となりますが、次のようなクエリを実行することで使用されているコンピュートノードの台数を確認することができます。(DMV 検索時にフィルターをしても有効なフィルターとなっていなかったため一時テーブルに挿入してから Request Id でフィルターしています)
DECLARE @dist_request_id uniqueidentifier = '<該当クエリの Distributed request ID>' DROP TABLE IF EXISTS #tmp DROP TABLE IF EXISTS #tmp2 DROP TABLE IF EXISTS #tmp3 SELECT * INTO #tmp FROM sys.dm_request_phases SELECT * FROM #tmp WHERE dist_request_id = @dist_request_id ORDER BY id ASC SELECT * INTO #tmp2 FROM sys.dm_request_phases_exec_task_stats SELECT * FROM #tmp2 WHERE dist_request_id = @dist_request_id ORDER BY id ASC SELECT * INTO #tmp3 FROM sys.dm_request_phases_task_group_stats SELECT * FROM #tmp3 WHERE dist_request_id = @dist_request_id ORDER BY id ASC
実際の実行結果が以下となります。
取得できる項目の中には「xxx_dop」という項目があり、これが並列度 (使用されるコンピュートノード数) を表しているかと思います。
operation_type | input_dop | output_dop |
Shuffle | 5 | 15 |
ComputeToControlNode | 15 | 1 |
Return | 1 | 1 |
この情報は、Azure ストレージの診断ログから情報を確認をした際と同様のクエリの情報となります。
Azure ストレージの診断ログから情報を取得した際には、5 台のコンピュートノードから、Azure ストレージのファイルがアクセスされていることが確認できました。
これに相当するのが「operation_type=Shuffle」の情報となるかと思います。
Shffule の input_dop は 5 となっており、これは Azure ストレージから確認できた台数と同じになっています。
5 台のコンピュートノードで、Azure ストレージからデータの取得が行われ、そのデータが 15 台のコンピュートノード (or CPU コア) にシャッフルされ、データが再分散されて集約処理が行われたということになります。(単純な検索であれば、「Shuffle」がなく、「CoputToControlNode」「Return」の構成となることもあります)
その後の処理としては「ComputeToControlNode」となり、15 に分割された処理が、コントロールノードに集約されて、「Return」で実行結果として返ってきたことが確認できます。
Azure ストレージの診断ログでは Azure ストレージ上のファイルのアクセス状況の確認となりますが、確認以降の分散処理の状況についてはこのような方法で確認をすることもできるのではないでしょうか。
まとめ
現時点では、Azure ストレージ上のファイルを T-SQL で検索する際のクエリエンジンとして、Synapse Analytics の Serverless SQL プールを活用するというシナリオは残るのではないでしょうか。
Serveless SQL プールで効率的処理を行うためには「どのように複数のコンピュートノードで分散して処理を行っているか」を意識することが重要となりますので、本投稿のような方法を使用して、実際の分散状況を意識して確認することも重要ではないでしょうか。