SQL 分析エンドポイントのパフォーマンスに関して考慮すべき事項

適用対象: Microsoft Fabric の SQL 分析エンドポイント

SQL 分析エンドポイントによって、T-SQL 言語と TDS プロトコルを使用してレイクハウスのデータに対してクエリを実行できます。 どのレイクハウスにも、SQL 分析エンドポイントが 1 つあります。 ワークスペース内の SQL 分析エンドポイントの数は、その同じワークスペースにプロビジョニングされたレイクハウスおよびミラー化されたデータベースの数に一致します。

バックグラウンド プロセスは、レイクハウスに変更がないかスキャンし、ワークスペース内のレイクハウスにコミットされたすべての変更を SQL 分析エンドポイントに反映して最新の状態に保ちます。 同期プロセスは、Microsoft Fabric プラットフォームによって透過的に管理されます。 レイクハウスで変更が検出されると、バックグラウンド プロセスがメタデータを更新し、レイクハウス テーブルにコミットされた変更が SQL 分析エンドポイントに反映されます。 通常の動作条件であれば、レイクハウスと SQL 分析エンドポイント間のタイムラグは 1 分未満です。

ガイダンス

  • 自動メタデータ検出は、レイクハウスにコミットされた変更を追跡する機能であり、Fabric ワークスペースごとに 1 つあるインスタンスです。 レイクハウスと SQL 分析エンドポイントとの間で変更が同期されるまでの待機時間が長くなっている場合は、1 つのワークスペースに多数のレイクハウスが存在することが原因である可能性があります。 このような状況では、各レイクハウスを個別のワークスペースに移行することを検討してください。自動メタデータ検出によるスケーリングが可能になります。
  • Parquet ファイルは変更できない仕様になっています。 更新操作や削除操作がある場合、変更セットとともに新しい Parquet ファイルが Delta テーブルに追加されます。更新や削除の頻度によっては、時間が経つにつれてファイルの数が増えていきます。 スケジュールされたメンテナンスがない場合、このパターンが続くと、最終的には読み取りのオーバーヘッドが発生し、SQL 分析エンドポイントに変更を同期するまでの時間に影響が出ます。 これに対処するには、レイクハウス テーブル メンテナンス操作を定期的に行うようスケジュールしてください。
  • 状況によっては、レイクハウスにコミットされた変更が関連する SQL 分析エンドポイントに表示されないことがあります。 たとえば、レイクハウスに新しいテーブルを作成したのに、SQL 分析エンドポイントにそのテーブルが表示されないといったことがあります。 あるいは、レイクハウス内のテーブルに多数の行をコミットしたのに、そのデータが SQL 分析エンドポイントに表示されないということもあり得ます。 メタデータ同期は、SQL クエリ エディターの [更新] リボン オプションからトリガーしてオンデマンドで開始することをお勧めします。 このオプションを選択すると、バックグラウンドでメタデータ同期が終了するのを待つのではなく、メタデータ同期がオンデマンドで強制的に開始されます。 SQL 分析エンドポイントのツールバーにあるオンデマンド更新ボタンを示す Fabric ポータルのスクリーンショット。

パーティション サイズに関して考慮すべき事項

レイクハウス内の Delta テーブルにあるパーティション列を選択するという操作は、SQL 分析エンドポイントに変更を同期するのにかかる時間に影響を与えます。 パフォーマンスを考えた場合、パーティション列のパーティションの数とサイズが重要になります。

  • カーディナリティが高い (大部分または全部が一意の値で構成されている) 列の場合、パーティションの数が非常に多くなります。 パーティションの数が非常に多くなると、変更がないかメタデータ検出スキャンを実施する際のパフォーマンスに悪影響を与えます。 列のカーディナリティが高い場合は、パーティション分割には別の列を選択してください。
  • 各パーティションのサイズも、パフォーマンスに影響を与えることがあります。 1 GB 以上 (かそれに近い) パーティションになるような列を使用することをお勧めします。 Delta テーブルのメンテナンス最適化のベスト プラクティスに従うことをお勧めします。 Python スクリプトによるパーティションの評価については、「パーティションの詳細に関するサンプル スクリプト」を参照してください。

小さなサイズの Parquet ファイルが大量にあると、レイクハウスとその関連する SQL 分析エンドポイントとの間で変更を同期する際にかかる時間が長くなります。 Delta テーブルに多数の Parquet ファイルが存在する場合、次に示すようにいくつか要因があります。

  • パーティションの対象として一意の値の数が多い Delta テーブルを選択すると、一意の値ごとにパーティション分割されて、過剰にパーティションが生成される可能性があります。 カーディナリティが高くなく、個々のパーティション サイズが 1 GB 以上になるパーティション列を選択してください。
  • バッチおよびストリーミング データ インジェスト率も、変更の頻度とサイズによっては、小さなファイルがレイクハウスに書き込まれる要因となることがあります。 たとえば、レイクハウスに加えられる変更のサイズが小さい場合、Parquet ファイルのサイズも小さくなります。 これに対処するには、定期的なレイクハウス テーブル メンテナンスを導入することをお勧めします。

パーティションの詳細に関するサンプル スクリプト

以下のノートブックを使用して、Delta テーブルを支えるパーティションのサイズと詳細について詳しく説明したレポートを印刷してください。

  1. まず、変数 delta_table_path に Delta テーブルの ABSFF パスを指定する必要があります。
    • Delta テーブルの ABFSS パスは、Fabric ポータルのエクスプローラーから取得できます。 テーブル名を右クリックし、オプションの一覧から COPY PATH を選択します。
  2. このスクリプトは、Delta テーブルのパーティションをすべて出力します。
  3. 各パーティションを反復処理して、ファイルの合計サイズと数を計算します。
  4. パーティション、パーティションごとのファイル、パーティションごとのサイズ (GB 単位) の詳細を出力します。

以下のコード ブロックからスクリプト全体をコピーできます。

# Purpose: Print out details of partitions, files per partitions, and size per partition in GB.
  from notebookutils import mssparkutils

# Define ABFSS path for your delta table. You can get ABFSS path of a delta table by simply right-clicking on table name and selecting COPY PATH from the list of options.
  delta_table_path = "abfss://<workspace id>@<onelake>.dfs.fabric.microsoft.com/<lakehouse id>/Tables/<tablename>"

# List all partitions for given delta table
partitions = mssparkutils.fs.ls(delta_table_path)

# Initialize a dictionary to store partition details
partition_details = {}

# Iterate through each partition
for partition in partitions:
  if partition.isDir:
      partition_name = partition.name
      partition_path = partition.path
      files = mssparkutils.fs.ls(partition_path)
      
      # Calculate the total size of the partition

      total_size = sum(file.size for file in files if not file.isDir)
      
      # Count the number of files

      file_count = sum(1 for file in files if not file.isDir)
      
      # Write partition details

      partition_details[partition_name] = {
          "size_bytes": total_size,
          "file_count": file_count
      }
      
# Print the partition details
for partition_name, details in partition_details.items():
  print(f"{partition_name}, Size: {details['size_bytes']:.2f} bytes, Number of files: {details['file_count']}")