SQL 分析端点性能注意事项

借助 SQL 分析终结点,可以使用 T-SQL 语言和 TDS 协议查询 Lakehouse 中的数据。

小窍门

有关优化 Delta 表用于 SQL 分析终结点使用的全面跨工作负载指南,包括文件大小建议和行组建议,请参阅 跨工作负载表维护和优化

每个湖屋都有一个 SQL 分析端点。 工作区中的 SQL 分析端点数与在该工作区中预配的湖屋镜像数据库数匹配。

后台进程负责扫描 lakehouse 中的更改,并使 SQL 分析终结点针对工作区中各个 lakehouse 里提交的所有更改保持最新。 Microsoft Fabric平台以透明方式管理同步过程。 当在湖屋中检测到更改时,后台进程会更新元数据,SQL 分析端点会反映提交给湖屋表的更改。 在正常操作条件下,湖屋和 SQL 分析端点之间的滞后时间不到一分钟。 根据本文讨论的许多因素,实际时间长度可能从几秒钟到分钟不等。 仅当 SQL 分析终结点处于活动状态且在处于非活动状态 15 分钟后停止时,后台进程才会运行。

Guidance

  • 自动元数据发现跟踪提交给 Lakehouse 的更改,并且在每个 Fabric 工作区中是一个单独的实例。 如果您发现湖屋与 SQL 分析终结点之间的更改同步延迟增加,这可能是因为单个工作区中存在大量湖屋。 在这种情况下,请考虑将每个湖仓迁移到单独的工作区,这样可使自动元数据发现实现扩展。
  • Parquet 文件本质上是不可变的。 当发生更新或删除操作时,Delta 表会添加包含变更集的新 Parquet 文件。随着时间推移,文件数量会增加,具体取决于更新和删除操作的频率。 如果不计划维护,此模式最终将产生读取开销,此条件会影响将更改同步到 SQL 分析终结点所需的时间。 若要解决此问题,请定期安排湖仓表维护作业
  • 在某些情况下,你可能会发现,提交到 Lakehouse 的更改在关联的 SQL 分析终结点中不可见。 例如,可以在 Lakehouse 中创建新表,但尚未在 SQL 分析终结点中列出。 或者,你可能已向 Lakehouse 中的表提交了大量行数据,但这些数据在 SQL 分析终结点中暂时还不可见。 可以选择 启动按需元数据同步
  • 自动同步过程不支持所有 Delta 功能。 有关 Fabric 中每个引擎支持的功能的详细信息,请参阅 Delta Lake 表格式互作性
  • 如果在提取转换和加载 (ETL) 处理期间存在非常大的表更改,则在处理所有更改之前会发生预期的延迟。

优化 Lakehouse 表以查询 SQL 分析终结点

当 SQL 分析终结点读取存储在 Lakehouse 中的表时,查询性能在很大程度上取决于基础 Parquet 文件的物理布局。

大量小型 Parquet 文件会产生开销,并会对查询性能产生负面影响。 为了确保性能可预测且高效,请管理表存储,使每个 Parquet 文件包含 200 万行数据。 此行计数提供均衡的并行度级别,而不会将数据集分段成过小的切片。

除了行计数指南之外,文件大小同样重要。 当 Parquet 文件足够大、能够最大限度地减少文件处理开销,但又不至于大到限制并行扫描效率时,SQL 分析端点的性能最佳。 对于大多数工作负荷,使单个 Parquet 文件保持接近 400 MB 会达到最佳平衡。 若要实现此平衡,请使用以下步骤:

  1. 在数据发生更改之前,将 maxRecordsPerFile 设置为 2,000,000。
  2. 执行数据更改(数据引入、更新、删除)。
  3. maxFileSize 设置为 4 GB。
  4. 运行 OPTIMIZE。 有关使用 OPTIMIZE 的详细信息,请参阅 在 Lakehouse 中运行表维护

以下脚本提供了这些步骤的模板,应在 Lakehouse 上执行:

from delta.tables import DeltaTable

# 1. CONFIGURE LIMITS

# Cap files to 2M rows during writes. This should be done before data ingestion occurs. 
spark.conf.set("spark.sql.files.maxRecordsPerFile", 2000000)

# 2. INGEST DATA
# Here, you ingest data into your table 

# 3. CAP FILE SIZE (~4GB)
spark.conf.set("spark.databricks.delta.optimize.maxFileSize", 4 * 1024 * 1024 * 1024)

# 4. RUN OPTIMIZE (bin-packing)
spark.sql("""
    OPTIMIZE myTable
""")

为保持合理的文件大小,请定期运行 Delta 优化操作,例如 OPTIMIZE,尤其是那些频繁进行增量插入、更新和删除的表。 这些维护作会将小型文件压缩成适当大小的文件,帮助确保 SQL 分析终结点能够高效地处理查询。

注释

有关 Lakehouse 表常规维护的指导,请参阅 Lakehouse 的运行表维护

分区大小注意事项

为湖屋中的增量表选择分区列也会影响将更改同步到 SQL 分析端点所需的时间。 分区列的分区数量和大小对于性能很重要:

  • 基数较高的列(大部分或全部由唯一值组成)会导致大量分区。 大量分区会对元数据发现扫描更改的性能产生负面影响。 如果某一列的基数很高,请选择另一列进行分区。
  • 每个分区的大小也会影响性能。 使用能够使分区大小达到至少 1 GB(或接近 1 GB)的列。 遵循Delta 表维护优化的最佳实践。 有关用于评估分区的Python脚本,请参阅 Sample 脚本了解分区详细信息

大量小型 parquet 文件会增加在湖屋与其关联的 SQL 分析端点之间同步更改所需的时间。 您可能会由于一个或多个原因,最终在 Delta 表中生成大量的 parquet 文件:

  • 如果选择具有大量唯一值的 Delta 表的分区,则表按每个唯一值进行分区,并且可能会过度分区。 选择不具有高基数的分区列,并确保每个分区至少为 1 GB。
  • 批处理和流式传输数据的引入速率可能会因写入数据湖屋的更改频率和大小而导致生成较小的文件。 例如,可能会有少量更改传入“Lakehouse”,从而导致生成小型 parquet 数据文件。 若要解决此问题,请实现常规 Lakehouse 表维护

分区详细信息的示例脚本

使用以下笔记本打印一份详细说明支撑增量表的分区的大小和详细信息的报告。

  1. 首先,为变量 delta_table_path中的 delta 表提供 ABFSS 路径。
    • 可以通过 Fabric 门户的资源管理器获取增量表的 ABFSS 路径。 右键单击表名,然后从选项列表中选择 COPY PATH
  2. 该脚本会输出增量表的所有分区。
  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']}")

Lakehouse 的 SQL 分析端点中自动生成的架构

对于 Lakehouse 中的每个 Delta 表,SQL 分析终结点都会在适当的架构中自动生成一个表。 SQL 分析终结点引擎基于Fabric Data Warehouse引擎。

有关详细信息,请参阅 SQL Analytics 终结点元数据同步。还可以使用 刷新 SQL 终结点元数据 REST API 以编程方式强制刷新自动元数据扫描。