适用于:✅Microsoft Fabric 中的仓库
本文包含有关数据仓库和 SQL 分析终结点中的数据引入、表管理、数据准备、统计信息和查询的最佳做法。 性能优化和优化可能会带来独特的挑战,但它们也提供了宝贵的机会来最大化数据解决方案的功能。
若要监视仓库的性能,请参阅 Monitor Fabric 数据仓库。
数据类型优化
选择正确的数据类型对于仓库中的性能和存储效率至关重要。 以下准则有助于确保架构设计支持快速查询、高效存储和可维护性。
有关 Fabric 数据仓库支持的数据类型的详细信息,请参阅 Fabric 数据仓库中的数据类型。
小窍门
如果使用外部工具生成表或查询,例如使用代码优先部署方法,请仔细查看列数据类型。 字符数据类型长度和查询应遵循这些最佳做法。
将数据类型与数据语义匹配
为了确保清晰度和性能,请务必使每列的数据类型与其存储的数据的实际性质和行为保持一致。
- 将 日期、 时间或 datetime2(n) 用于时态值,而不是将它们存储为字符串。
- 除非需要格式设置(例如前导零),否则对数值使用整数类型。
- 保留格式时使用字符类型(char,varchar)至关重要(例如,可以以零开头的数字、产品代码、带短划线的数字)。
对整数使用整数类型
存储标识符、计数器或其他整数等值时,首选整数类型(smallint、 int、 bigint)而不是 十进制/数字。 整数类型需要的存储量小于允许小数点右侧的数字的数据类型。 因此,它们允许更快的算术和比较运算,并提高索引和查询性能。
请注意 Fabric 数据仓库支持的每个整数数据类型的值范围。 有关详细信息,int、bigint、smallint(Transact-SQL)。
考虑十进制和数值精度及小数位数的使用
如果必须使用 十进制/数字,则创建列时选择可容纳数据的最小 精度和小数位数 。 过度预配精度会增加存储要求,并随着数据的增长而降低性能。
- 预测仓库的预期增长和需求。 例如,如果计划将不超过四位数字存储在小数点右侧,请使用 十进制(9,4) 或十 进制(19,4) 进行最高效的存储。
- 创建 十进制/数字 列时,始终指定精度和刻度。 当在定义为仅
decimal
的表中创建时,如果不指定(p,s)
精度和小数位数,则会创建一个decimal(18,0)
十进制数字列。 精度为 18 的 Decimal 数据类型每行占用 9 个字节的存储空间。 不能存储小数点右侧数据的刻度0
。 对于许多企业整型数,smallint、int、bigint 的效率比decimal(18,0)
高得多。 例如,任何九位数整数都可以存储为 整数 数据类型,每行存储 4 字节。
有关完整信息,请参阅十进制和数字(Transact-SQL)。
考虑何时使用 varchar 而不是 char
除非明确需要固定长度填充,否则应在字符串列中使用varchar(n)而不是char(n)。 varchar 列仅存储每行的实际字符串长度,以及较小的开销,并减少浪费的空间,从而提高 I/O 效率。
- 将 varchar(n) 用于名称、地址和说明等值,因为它们具有广泛的变量值。 当数据类型长度对实际数据更精确时,统计信息和查询成本估算更准确。
- 如果知道字符串每次都将是固定长度,请使用 char(n )。 例如,如果将字符串
000000000
存储为 char(9), 则字符串始终是 9 个数字字符,可以从零开始。 - 列数据类型声明中的长度
n
是存储字节。 对于多字节编码字符集(如 UTF-8),Fabric 数据仓库中的拉丁字符和数字的编码采用 1 字节存储。 但是,存在需要 1 个字节以上的 Unicode 字符,例如需要 3 个字节的日语字符来存储,因此实际存储的 Unicode 字符数可以小于数据类型长度n
。 有关详细信息,请参阅 char 和 varchar 参数。
尽可能避免可以为 null 的列
当数据模型允许时,将列定义为 NOT NULL
。 默认情况下,表中的列允许 NULL
值。 允许为空的列具有以下特征:
- 它们增加了元数据开销。
- 可以降低查询优化和统计信息的有效性。
- 可能会影响大规模分析查询的性能。
将数据导入和准备到数据仓库
复制到
建议使用 T-SQL COPY INTO 命令将数据从 Azure Data Lake Storage 引入 Fabric 数据仓库。 有关详细信息和示例,请参阅 使用 COPY 语句将数据引入仓库。
请考虑以下建议,以获得最佳性能:
- 文件大小: 确保引入的每个文件最好在 100 MB 到 1 GB 之间,以实现最大化的吞吐量。 这有助于优化引入过程并提高性能。
- 文件数: 若要最大程度地提高并行度和查询性能,旨在生成大量文件。 优先创建尽可能多的文件,同时保持最小文件大小为 100 MB。
-
并行加载: 利用并行运行的多个
COPY INTO
语句将数据加载到不同的表中。 由于并行度,此方法可以显著减少 ETL/ELT 窗口。 - 容量大小:对于较大的数据卷,请考虑横向扩展到更大的结构容量,以获取容纳更多并行处理和较大数据卷所需的额外计算资源。
Fabric 数据仓库还支持 BULK INSERT
作为同义词的 COPY INTO
语句。 相同的建议适用于 BULK INSERT
语句。
CTAS 或 INSERT
使用 CREATE TABLE AS SELECT(CTAS) 或 INSERT
与 SELECT FROM
Lakehouse 表/快捷方式命令结合使用。 与使用管道相比,这些方法的性能和效率可能更高,因此可以更快、更可靠的数据传输。 有关详细信息和示例,请参阅 使用 Transact-SQL 将数据引入仓库。
增加并行数量和扩展到更大的架构容量的概念也适用于 CTAS/INSERT操作,以提高吞吐量。
使用 OPENROWSET 从 Azure Data Lake Storage 或 Blob 存储读取数据
OPENROWSET 函数允许从 Azure Data Lake 或 Azure Blob 存储读取 CSV 或 Parquet 文件,而无需将其引入仓库。 有关详细信息和示例,请参阅 使用 OPENROWSET 函数浏览文件内容。
使用 OPENROWSET 函数读取数据时,请考虑以下建议以获得最佳性能:
- Parquet: 如果经常查询文件,请尝试使用 Parquet 而不是 CSV,或将 CSV 转换为 Parquet。 Parquet 是一种分列格式。 由于数据已压缩,因此其文件大小小于包含相同数据的 CSV 文件。 如果要读取 Parquet 文件,Fabric 数据仓库将跳过查询中不需要的列和行。
- 文件大小: 确保引入的每个文件最好在 100 MB 到 1 GB 之间,以实现最大化的吞吐量。 这有助于优化引入过程并提高性能。 最好拥有大小相同的文件。
- 文件数: 若要最大程度地提高并行度和查询性能,旨在生成大量文件。 优先创建尽可能多的文件,同时保持最小文件大小为 100 MB。
- 分区: 如果你的工作负载是通过分区列来筛选数据,可以通过将分区存储在不同的文件夹或文件名中来对数据进行分区。
-
估计: 如果觉得没有获得预期的性能,请尝试设置
ROWS_PER_BATCH
以匹配基础文件中的行数。 - 容量大小: 对于较大的数据量,请考虑横向扩展到更大的 SKU,以获取更多计算资源,从而支持更多并行处理和更大的数据量。
避免逐步插入、更新和删除操作
为了确保结构数据仓库中的高效文件布局和最佳的查询性能,请避免使用许多小型INSERT
UPDATE
和DELETE
事务。 这些行级更改会为每个操作生成一个新的 Parquet 文件,从而产生大量小型文件和碎片化的行组。 这种碎片化会导致:
- 由于文件扫描效率低下,查询延迟增加。
- 更高的存储和计算成本。
- 更依赖后台压缩过程。
建议的方法:
- 写入 Fabric 数据仓库的批处理事务。
- 例如,预先将数据暂存到一起,并在一个
INSERT
语句中插入数据,而不是使用许多小INSERT
语句。
- 例如,预先将数据暂存到一起,并在一个
- 使用 COPY INTO 进行批量插入,并尽可能批量执行更新和删除。
- 请保持导入文件的最小大小为100 MB,以确保高效形成行组。
- 有关数据引入的更多指南和最佳做法,请参阅 将数据引入仓库的最佳做法。
数据压缩
在 Fabric 数据仓库中,数据压缩是 Fabric 数据仓库中的后台优化过程,可将小型、低效的 Parquet 文件合并为更少的大型文件。 这些文件通常是由频繁的涓流INSERT
、UPDATE
或DELETE
操作创建的。 数据压缩可减少文件碎片,提高行组效率,并提高整体查询性能。
尽管 Fabric 数据仓库引擎通过数据压缩自动解析碎片,但在进程完成之前,性能可能会下降。 数据压缩自动运行,无需用户干预 Fabric 数据仓库。
数据压缩不适用于 Lakehouse。 对于通过 SQL 分析终结点访问的 Lakehouse 表,请务必遵循 Lakehouse 最佳做法,并在重大数据更改后手动运行 OPTIMIZE 命令 ,以保持最佳存储布局。
Fabric 数据仓库中的 V-Order
V-Order 是一种用于 parquet 文件格式的写入时优化技术,使得在 Microsoft Fabric 中能够快速读取。 在 Fabric 数据仓库中,V-Order 通过对表文件应用排序和压缩来提高查询性能。
默认情况下,所有仓库都启用了 V-Order,以确保读取作(尤其是分析查询)尽可能快且高效。
但是,V-Order 引入了较小的引入开销,在写入密集型工作负荷中明显。 出于此原因,应仅针对严格写入密集型且不用于频繁查询的仓库考虑禁用 V-Order。 请务必注意,在仓库中禁用 V-Order 后,无法重新启用它。
在决定禁用 V 顺序之前,用户应全面测试其工作负荷性能,以确保权衡合理。 一种常见的模式是使用禁用 V 订单的暂存仓库来实现高吞吐量的数据加载和转换,然后将处理后的数据加载到启用 V 订单的数据仓库中,以提高读取性能。 有关详细信息,请参阅 Microsoft Fabric 中的“在仓库上禁用 V 订单”。
克隆表而不是复制表
Fabric 数据仓库中的表克隆 提供了一种快速高效的方法来创建表,而无需复制数据。 使用零复制克隆方法,仅复制表的元数据,而基础数据文件则直接从 OneLake 引用。 这样,用户几乎可以立即创建一致的可靠表副本,而不会造成完整数据复制的开销。
零复制克隆非常适合开发、测试和备份等方案,提供高性能、存储高效的解决方案,可帮助降低基础结构成本。
- 克隆的表还复制源中的所有关键 安全功能 ,包括 Row-Level 安全(RLS)、Column-Level 安全性(CLS)和动态数据掩码(DDM),而无需在克隆后重新应用策略。
- 可以在数据保留期内的特定时间点创建克隆,从而支持 时间旅行功能。
- 克隆的表独立于其源存在,对源所做的更改不会影响克隆,克隆的更改不会影响源。 可以独立删除源文件或克隆副本。
查询性能
统计信息
统计信息是表示表列中数据的持久化对象。 查询优化器使用统计信息来选取和估计查询计划的成本。 Fabric 数据仓库和 Lakehouse SQL 分析终结点使用并自动维护直方图统计信息、平均列长度统计信息和表基数统计信息。 有关详细信息,请参阅 Fabric 数据仓库中的统计信息。
- 支持单列直方图统计信息的 T-SQL 命令包括 CREATE STATISTICS 和 UPDATE STATISTICS。 如果表转换和查询工作负荷之间存在足够大的窗口,例如在维护时段或其他停机期间,则可以利用这些窗口。 这减少了你的查询需先更新统计信息的可能性
SELECT
。 - 尝试定义在常见列比较中维护数据类型奇偶校验的表架构。 例如,如果知道列在
WHERE
子句中经常相互比较,或者用作JOIN ... ON
的谓词,请确保数据类型匹配。 如果无法使用完全相同的数据类型,请使用与隐式转换兼容的类似数据类型。 避免显式数据转换。 有关详细信息,请参阅数据类型转换。
小窍门
对于 Lakehouse 用户,ACE-Cardinality 统计信息可以利用表中的 Delta 日志文件里的信息来提高准确性。 确保 Spark 生成的 Delta 表包含表行计数:spark.conf.set("spark.databricks.delta.stats.collect", "true")
有关详细信息,请参阅 在 Fabric Spark 中配置和管理自动表统计信息。
在 Apache Spark 运行时 3.5.0 之前筛选时间戳列上的 Lakehouse 表时,不会生成时间戳列的行组级统计信息。 这种缺乏统计信息使得像 Fabric Warehouse 这样的系统难以应用行组排除(也称为数据跳过或谓词下推)性能优化,在查询执行期间跳过不相关的行组。 如果没有这些统计信息,筛选涉及时间戳列的查询可能需要扫描更多数据,从而导致性能显著下降。 可以在 Fabric 中升级 Apache Spark 运行时。 Apache Spark 3.5.0 及更高版本可以为时间戳列生成行组级统计信息。 然后,需要重新创建表并引入数据以生成行组级别统计信息。
冷缓存性能
在 Fabric 数据仓库中 首次执行 查询的速度可能会意外地比后续运行慢。 这称为 冷启动,由系统初始化或缩放活动导致,这些活动准备环境以供处理。
冷启动通常在以下情况下发生:
- 数据从 OneLake 加载到内存中,因为它第一次被访问,并且尚未缓存。
- 如果首次访问数据,查询执行将延迟,直到自动生成必要的 统计信息 。
- Fabric 数据仓库在一段时间处于非活动状态后自动暂停节点,以降低成本,并将节点添加为自动缩放的一部分。 恢复或创建节点通常需要不到一秒的时间。
这些操作可能会增加查询的持续时间。 冷启动可以是部分的。 某些计算节点、数据或统计信息可能已在内存中可用或缓存,而查询将等待其他节点可用。 有关详细信息,请参阅 Fabric 数据仓库中的缓存。
可以通过查询 queryinsights.exec_requests_history 视图来检测从远程存储提取数据到内存造成的冷启动效果。 检查 data_scanned_remote_storage_mb
列:
-
data_scanned_remote_storage_mb
中的非零值表示冷启动。 在执行查询期间从 OneLake 提取数据。 后续视图的运行速度应在queryinsights.exec_requests_history
明显更快并可证明。 - 零
data_scanned_remote_storage_mb
值是缓存所有数据的最佳状态。 不需要 OneLake 中的节点更改或数据来提供查询结果。
重要
不要根据 第一次 执行来判断查询性能。 始终检查 data_scanned_remote_storage_mb
以确定查询是否受冷启动的影响。 后续执行通常要快得多,并代表实际性能,这将降低平均执行时间。
对包含字符串列的表的查询
使用可容纳值的最小字符串列长度。 Fabric Warehouse 正在不断改进;但是,如果使用大型字符串数据类型,尤其是大型对象(LOBs),则可能会遇到性能不理想的情况。 例如,对于customer_name
列的数据类型,考虑您的业务需求和预期数据,并在声明varchar(n)
时使用合适的长度n
,例如varchar(100),而不是varchar(8000)或varchar(max)。 当数据类型长度对实际数据更精确时,统计信息和查询成本估算更准确。
- 在 Fabric 数据仓库 T-SQL 中,请参阅 有关为字符串数据类型选择适当长度的指南。
- Fabric Warehouse 将 Spark 中没有定义长度的 Lakehouse 表字符串列识别为 varchar(8000)。 为了获得最佳性能,请使用
CREATE TABLE
SparkSQL 中的语句将字符串列varchar(n)
定义为,其中n
最大列长度可以容纳值。
事务和并发
Fabric 数据仓库基于现代云原生体系结构构建,它结合了事务完整性、快照隔离和分布式计算,以大规模提供高并发性和一致性。 如需更多信息,请参阅 仓库表中的事务。
Fabric 数据仓库支持使用快照隔离的符合 ACID 的事务。 这意味着:
- 可以使用标准 T-SQL(
BEGIN TRANSACTION
、COMMIT
、ROLLBACK
) 将读取和写入作分组到单个事务中 - 全有或全无语义:如果事务跨越多个表,其中一个操作失败,则会回滚整个事务。
- 读取一致性:
SELECT
事务中的查询会看到数据的一致快照,不受并发写入影响。
Fabric 仓库交易支持:
-
事务内的数据定义语言(DDL): 可以在事务块中包括
CREATE TABLE
。 - 跨数据库事务: 在同一工作区中受支持,包括从 SQL 分析终结点读取数据。
- 基于 Parquet 的回滚: 由于 Fabric 数据仓库将数据存储在不可变的 Parquet 文件中,回滚速度很快。 回滚操作仅仅是还原到先前的文件版本。
- 自动数据压缩和检查点:数据压缩通过合并小型 Parquet 文件和移除逻辑上已删除的行来优化存储和读取性能。
-
自动检查点:每次写入操作(
INSERT
,UPDATE
,DELETE
)都会将新的 JSON 日志文件追加到 Delta Lake 事务日志。 随着时间的推移,这可能会导致数百或数千个日志文件,尤其是在流式处理或高频率引入方案中。 自动检查点通过将事务日志汇总到单个检查点文件中来提高元数据读取效率。 如果没有检查点,每次读取都必须扫描整个事务日志历史记录。 使用检查点时,仅读取最新的检查点文件和其后的日志。 这大大减少了 I/O 和元数据分析,尤其是对于大型或频繁更新的表。
压缩和检查点对于维持表的健康运行至关重要,尤其是在长时间运行或高并发的环境中。
并发控制和隔离
Fabric 数据仓库专门使用快照隔离。 忽略通过 T-SQL 更改隔离级别的尝试。
事务处理的最佳实践
- 明智地使用显式事务。 始终
COMMIT
或ROLLBACK
。 不要让事务保持打开状态。- 使事务保持生命周期较短。 避免长时间占用系统资源的事务,不必要地持有锁,尤其是对于包含 DDL 的显式声明的事务。 这可能会导致系统
SELECT
目录视图(如sys.tables
)上的语句争用,并可能导致依赖于系统目录视图的 Fabric 门户出现问题。
- 使事务保持生命周期较短。 避免长时间占用系统资源的事务,不必要地持有锁,尤其是对于包含 DDL 的显式声明的事务。 这可能会导致系统
- 在管道或应用中添加延迟的重试逻辑,以处理暂时性冲突。
- 使用指数退避以避免使暂时性网络中断恶化的重试风暴。
- 有关详细信息,请参阅重试模式。
- 监视仓库中的锁和冲突。
- 使用 sys.dm_tran_locks 检查当前锁。
减少返回的数据集大小
在中间查询执行或最终查询结果中,数据大小较大的查询可能会遇到更多的查询性能问题。 若要减小返回的数据集大小,请考虑以下策略:
- 在 Lakehouse 中对大型表进行分区。
- 限制返回的列数。
SELECT *
成本可能很高。 - 限制返回的行数。 尽可能多地在仓库中执行数据筛选,而不是在客户端应用程序中执行。
- 尝试在联接之前进行筛选,以在查询执行初期减少数据集。
- 筛选低基数列,以在 JOIN 之前提前减少大型数据集。
- 具有高基数的列非常适合筛选和 JOIN 操作。 这些元素通常用于
WHERE
子句,并通过在查询执行的早期阶段应用谓词来受益于对数据的筛选。
- 在 Fabric 数据仓库中,由于不强制实施主键和唯一键约束,因此具有这些约束的列不一定适合 JOIN。
查询计划和查询提示
在 Fabric 数据仓库中,查询优化器生成查询执行计划,以确定执行 SQL 查询的最有效方法。 高级用户可以考虑通过查询计划或添加查询提示来调查查询性能问题。
- 用户可以在 SQL Server Management Studio 中使用SHOWPLAN_XML来查看计划,而无需执行查询。
- 可以选择性 查询提示 添加到 SQL 语句,以在生成计划之前向查询优化器提供更多说明。 添加查询提示需要对查询工作负荷的高级知识,因此通常在实施其他最佳做法后使用,但问题仍然存在。
不可缩放的操作
Fabric 数据仓库基于大规模并行处理(MPP)体系结构构建,可在多个计算节点上执行查询。 在某些情况下,单节点执行是合理的:
- 整个查询计划执行只需要一个计算节点。
- 计划子树可以容纳在一个计算节点中。
-
必须在单个节点上执行整个查询或查询的一部分,以满足查询语义。 例如,
TOP
操作、全局排序、需要对并行执行结果进行排序以生成单一结果的查询,或联接结果以完成最终步骤。
在这些情况下,用户可以收到警告消息“检测到一个或多个不可缩放的操作”,且查询可能会在长时间执行后变得缓慢或失败。
- 请考虑减小查询筛选数据集的大小。
- 如果查询语义不需要单节点执行,请尝试使用 FORCE DISTRIBUTED PLAN 强制分布式查询计划,例如
OPTION (FORCE DISTRIBUTED PLAN);
。
查询 SQL 分析终结点
可以使用 SQL 分析终结点查询使用 Spark SQL 填充的 Lakehouse 表,而无需将数据复制或引入仓库。
以下最佳做法适用于通过 SQL 分析终结点查询 Lakehouse 中的仓库数据。 有关 SQL 分析终结点性能的详细信息,请参阅 SQL 分析终结点性能注意事项。
小窍门
以下最佳做法应用于使用 Spark 将数据处理到可由 SQL 分析端点查询的数据湖仓库中。
定期对 Lakehouse 表进行维护
在 Microsoft Fabric 中,仓库会自动优化数据布局,并执行垃圾回收和压缩。 对于 Lakehouse,你可以更好地控制 表维护。 表优化和清扫是必需的,可以显著减少大型数据集所需的扫描时间。 Lakehouse 中的表维护还扩展到快捷方式,有助于显著提高性能。
优化包含许多小文件的 Lakehouse 表或快捷方式
拥有许多小文件会导致读取文件元数据的额外开销。 使用 Fabric 门户中的 OPTIMIZE 命令 或笔记本将小文件合并为较大的文件。 当文件数量发生显著更改时重复此过程。
若要优化 Fabric Lakehouse 中的表,请在 Fabric 门户中打开 Lakehouse。 在 资源管理器中,右键单击表,选择“ 维护”。 从 “运行维护命令 ”页中选择选项,然后选择“ 立即运行”。
查询位于同一区域中的 Lakehouse 表或快捷方式
Fabric 使用位于其容量所在位置的计算资源。 查询数据,例如,在您自己的 Azure Data Lake Storage 或 OneLake 中,从其他区域进行查询时会由于网络延迟导致性能开销。 确保数据位于同一区域。 根据性能要求,请考虑仅保留小型表,如偏远地区中的维度表。
筛选 Lakehouse 表和快捷方式,以相同的列为基础
如果经常筛选特定列上的表行,请考虑对表进行分区。
分区适用于低基数列或具有可预测基数的列(如年份或日期)。 有关详细信息,请参阅 Lakehouse 教程 - 使用分区准备和转换 Lakehouse 数据 并将 数据加载到 Lakehouse。
聚类分析适用于高选择性列。 如果你有其他经常用于筛选的列,而不是分区列,请考虑使用 Spark SQL 语法 ZORDER BY
的优化来聚类化表。 有关详细信息,请参阅 Delta Lake 表优化。
查询元数据视图
查询执行历史记录 (30 天)
聚合见解
有关 queryinsights
视图的更多信息,请参阅 Fabric 数据仓库中的查询分析。
- 查询生命周期的动态管理视图 (DMV)
有关查询生命周期 DMV 的详细信息,请参阅 使用 DMV 监视连接、会话和请求。