你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
提示
Microsoft Fabric Data Warehouse是数据湖基础上的企业规模关系仓库,具有未来就绪的体系结构、内置 AI 和新功能。 如果不熟悉数据仓库,请从Fabric Data Warehouse开始。 现有的指定 SQL 池工作负荷可以升级到 Fabric,以跨数据科学、实时分析和报告访问新功能。
本文提供了一系列最佳做法,有助于你在 Azure Synapse Analytics 中实现专用 SQL 池的最佳性能。 如果你使用的是无服务器 SQL 池,请参阅无服务器 SQL 池的最佳做法获取具体指导。 下面你将找到构建解决方案时需要关注的基本指南和重要领域。 每部分都介绍了一个概念,并为你指出了更深入介绍该概念的更详细的文章。
专用 SQL 池加载
有关专用 SQL 池加载指南,请参阅数据加载指南。
使用暂停和缩放来降低成本
若要了解如何通过暂停和缩放来降低成本,请参阅管理计算。
维护统计信息
可以将专用 SQL 池配置为自动检测列并为其创建统计信息。 优化器创建的查询计划的好坏取决于可用的统计信息。
建议为数据库启用 AUTO_CREATE_STATISTICS,并使统计信息每日更新或者在每次加载后更新,以确保查询中使用的有关列的统计信息始终保持最新。
要缩短统计信息维护时间,你需要选择需要做统计的列,或者需要频繁更新的列。 例如,你可能希望更新每天都要添加新值的日期列。 重点关注对涉及联接的列、WHERE 子句中使用的列,以及在 GROUP BY 中找到的列进行统计。
有关统计信息的其他信息,请参阅管理表统计信息、CREATE STATISTICS 和 UPDATE STATISTICS 文章。
调整查询性能
将 INSERT 语句分组以进行成批处理
根据您的需求,用 INSERT 语句(如INSERT INTO MyLookup VALUES (1, 'Type 1'))对小型表进行一次性加载可能是最佳方法。 但是,如果需要在一天中加载数千或数百万行,单次插入操作可能不是最佳选择。
解决此问题的一种方法是开发两个进程,一个用于写入文件,另一个用于定期加载此文件。 有关详细信息,请参阅 INSERT 一文。
使用 PolyBase 快速加载和导出数据
专用 SQL 池支持通过多种工具(包括 Azure 数据工厂、PolyBase 和 BCP)来加载和导出数据。 对于少量的数据,性能不是那么重要,任何工具都可以满足需求。
注意
在加载或导出大量数据,或需要更快的性能时,PolyBase 是最佳选择。
可使用 CTAS 或 INSERT INTO 来运行 PolyBase 加载。 CTAS 可以减少事务日志记录,是加载数据最快的方法。 Azure 数据工厂还支持 PolyBase 加载,并且可以实现与 CTAS 类似的性能。 PolyBase 支持各种不同的文件格式,包括 Gzip 文件。
若要在使用 Gzip 文本文件时获得最大的吞吐量,请将文件拆分成至少 60 个文件,以便最大程度提高加载的并行度。 若要更快的总吞吐量,请考虑并行加载数据。 有关本部分的其他信息,请参阅以下文章:
加载并查询外部表
PolyBase 不是查询的最佳选项。 专用 SQL 池的 PolyBase 表目前只支持 Azure blob 文件和 Azure Data Lake Storage。 这些文件并没有任何计算资源的支持。 因此,专用 SQL 池无法卸载此工作,必须读取整个文件,方法是将其加载到 tempdb 来读取数据。
如果有多个查询需要查询此数据,则最好是先加载一次此数据,然后让查询使用本地表。 更多 PolyBase 指南,请参阅 PolyBase 使用指南一文。
通过哈希分布大表
默认情况下,表是以“Round Robin”机制分布的。 此默认设置让用户可以轻松开始创建表,而不必确定表的分布方式。 轮转表可能足以应对某些工作负载。 但在大多数情况下,分布列提供的性能更好。
最常见的按列分布表性能优于轮转表的例子是两个大型事实表的联接。
例如,如果有一个依 order_id 分布的订单表,以及一个也是依 order_id 分布的事务表,当将订单表与事务表通过 order_id 进行联接时,此查询将变成通行查询。 然后,数据移动操作将被消除。 减少步骤意味着加快查询速度。 更少的数据移动也将让查询更快。
提示
加载分布式表时,不应对传入数据按分布键进行排序。 这样做会减慢负载。
下面提供的文章链接提供有关通过选择分布列提高性能的更多详细信息。 此外,你还可以在 CREATE TABLE 语句的 WITH 子句中找到有关如何定义分布式表的信息:
不要过度分区
尽管数据分区对于维护数据(通过分区切换)或优化扫描(通过分区排除)很有效,但分区过多会减慢查询速度。 通常,在 SQL Server 上运行良好的高粒度分区策略可能无法在专用 SQL 池中正常工作。
如果每个分区的行数少于 1 百万,分区过多会降低聚集列存储索引的效率。 专用 SQL 池会自动将数据分区为 60 个数据库。 因此,如果创建具有 100 个分区的表,将得到 6,000 个分区。 每个工作负载都不同,因此最佳建议是尝试不同的分区,找出最适合工作负载的分区。
可以考虑的一种选择是使用比通过 SQL Server 实现的更细的粒度。 例如,考虑使用每周或每月分区,而不是每日分区。
有关分区的详细信息,请参阅表分区一文。
最小化事务大小
INSERT、UPDATE 和 DELETE 语句在事务中运行。 当这些操作失败时,必须回退。 为了降低长时间回退的可能性,请尽可能将事务大小最小化。 这可以通过将 INSERT、UPDATE、DELETE 语句分成小部分来最小化事务大小。 例如,如果预期 INSERT 需要 1 小时,可将 INSERT 分成四个部分。 然后,每次运行将缩短为 15 分钟。
提示
利用特殊的最小日志记录方案(例如 CTAS、TRUNCATE、DROP TABLE 或将数据插入到空表中)来降低回滚的风险。
另一种避免回滚的方法是使用仅元数据操作,例如分区切换来进行数据管理。 例如,对于 order_date 为 2001 年 10 月的表,你可以按月对数据进行分区,而不是执行 DELETE 语句来删除该表中的所有行。 然后,你可以将包含数据的分区替换为来自另一个表的空分区(请参阅 ALTER TABLE 示例)。
对于未分区的表,请考虑使用 CTAS 将想要保留的数据写入表中,而不是使用 DELETE。 如果 CTAS 花费的时间相同,则运行起来要安全得多,因为它的事务日志记录最少,并且可以根据需要快速取消。
如需进一步了解本部分相关内容,请参阅以下文章:
缩减查询结果大小
缩减查询结果大小可帮助你避免由大型查询结果引起的客户端问题。 你可以编辑查询以减少返回的行数。 一些查询生成工具允许你向每个查询添加“top N”语法。 你还可以将查询结果 CETAS 到临时表,然后使用 PolyBase 导出进行下层处理。
使用最小可能的列大小
定义 DDL 时,请使用支持数据的最小数据类型以便提高查询性能。 此建议对于 CHAR 和 VARCHAR 列尤其重要。 如果列中最长的值是 25 个字符,请将列定义为 VARCHAR(25)。 避免将所有字符列定义为较大的默认长度。 此外,建议在只需定义为 VARCHAR 时,不要使用 NVARCHAR。
如需更详细地了解与上述信息相关的基本概念,请参阅文章表概述、表数据类型和 CREATE TABLE。
使用临时堆表处理临时数据
暂时将数据放置在专用 SQL 池上时,使用堆表通常会提高整个进程的速度。 如果加载数据只是为了在进行更多转换之前进行暂存,那么将表载入堆表会比将数据载入聚集列存储表要快。
将数据载入临时表也比将表载入永久存储更快速。 临时表以“#”开头,并且只能由创建它的会话访问。 因此,它们可能仅在有限的情况才起作用。 堆表在 CREATE TABLE 的 WITH 子句中定义。 如果使用临时表,请记得同时在该临时表上创建统计信息。
有关更多信息,请参阅临时表、CREATE TABLE 和 CREATE TABLE AS SELECT 文章。
优化聚集列存储表
聚集列存储索引是将数据存储在专用 SQL 池中最有效率的方式之一。 默认情况下,专用 SQL 池中的表默认创建为聚集列存储。 为了让列存储表的查询获得最佳性能,良好的分段质量很重要。 当行在内存不足的状态下写入列存储表时,列存储分段质量可能降低。
压缩行组中的行数可以测量分段质量。 有关检测和改善聚集列存储表分段质量的分步说明,请参阅表索引一文中的列存储索引质量不佳的原因。
由于高质量列存储段很重要,因此可以考虑使用中型或大型资源类中的用户 ID 来加载数据。 使用较低的数据仓库单位值意味着需要向加载用户分配较大的资源类。
列存储表通常不会将数据推送到压缩列存储段,除非每个表的行数超过 100 万。 每个专用 SQL 池表分布到 60 个不同的分布区。 因此,除非表具有 6,000 多万行,否则列存储表对查询没有益处。
提示
对于少于 6,000 万行的表,列存储索引可能不是最佳解决方案。
如果对数据进行分区,则每个分区需要具有 100 万行,这样使用聚集列存储索引才有益。 对于有 100 个分区的表,至少必须有 60 亿行才能受益于聚集列存储(60 个分布区 100 个分区 100 万行)。
如果表没有 60 亿行,则有两个主要选项。 减少分区数目,或考虑改用堆表。 使用具有辅助索引的堆表而不是列存储表也许能提升性能,值得试验。
查询列存储表时,如果只选择需要的列,查询运行将更快速。 有关表和列存储索引的详细信息,请参阅以下文章:
使用较大的资源类来改善查询性能
SQL 池使用资源组作为将内存分配给查询的一种方式。 最初,所有用户都分配到小资源类,该类为每个分布区提供 100 MB 内存。 总是有 60 个分布区。 每个分布至少为 100 MB。 系统范围内存分配总量为 6,000 MB,或略低于 6 GB。
某些查询,例如大型连接或向聚集列存储表载入数据,将受益于较大的内存分配。 某些查询,例如纯扫描,则不会获得任何好处。 使用较大的资源类别会影响并发性。 在将所有用户移动到大型资源类之前,你需要牢记这些事实。
有关资源类的详细信息,请参阅文章用于工作负载管理的资源类。
使用较小的资源集以提高并发性
如果你注意到用户查询延迟时间较长,则用户可能在较大的资源类中运行。 这种情况会加速并发槽的消耗,这可能导致其他查询排队。 若要确认用户的查询是否被排入队列,请运行 SELECT * FROM sys.dm_pdw_waits 查看是否返回了任何行。
有关详细信息,请参阅用于工作负载管理的资源类和 sys.dm_pdw_waits 文章。
使用动态管理视图 (DMV) 来监视和优化您的查询
专用 SQL 池有多个用于监控查询执行的动态管理视图 (DMV)。 以下监控文档逐步指导您如何查看执行中查询的详细信息。 若要在这些 DMV 中快速找到查询,可在查询中使用 LABEL 选项。 有关其他详细信息,请参阅以下列表中包含的文章:
相关内容
有关常见问题和解决方案,另请参阅疑难解答一文。
如果本文未提供你需要的问题,请搜索有关 Azure Synapse 的 Microsoft Q&A 问题页面以向其他用户和 Azure Synapse Analytics 产品组提出问题。
我们会主动观察此论坛,确保用户的问题获得其他用户或我们的回答。 如果你更喜欢在 Stack Overflow 上提问,还可以访问 Azure Synapse Analytics Stack Overflow 论坛。