刷新模式如何影响动态表性能

动态表的实际 刷新模式 在创建时确定,此后不可变。如果未显式指定,刷新模式默认为 AUTO,它会根据查询复杂性、不支持的构造、运算符或函数等各种因素选择刷新模式。

要验证动态表的刷新模式,请参阅 查看动态表刷新模式

小技巧

要确定最适合您用例的模式,请尝试自动建议和具体的刷新模式(完整和增量)。您动态表的最佳模式取决于数据变化量和查询复杂性。此外,使用专用仓库测试不同的刷新模式有助于隔离成本,并根据实际工作负载改善性能调优。

要在不同的 Snowflake 版本中保持一致的行为,请在所有生产表上显式设置刷新模式。AUTO 的行为可能会在 Snowflake 版本之间发生变化,这可能会导致在生产管道中使用时性能出现意外变化。

有关更多信息,请参阅 优化性能的最佳实践

完整刷新模式性能

完整刷新执行查询并使用结果覆盖动态表。动态表的内容无论选择完整刷新模式还是增量刷新模式都是相同的。

完整刷新通常用于复杂查询或工作负载,而增量刷新效率较低。

尽管完整刷新是资源密集型的,但在重新处理整个数据集时非常有用,例如对于 不支持的增量操 作 或重大数据更改。

为了优化完整刷新性能,将其 视为任何其他 Snowflake 查询,但请记住,成本包括执行查询和插入结果,而不仅仅是查询执行。

增量刷新模式性能

增量刷新专注于应用自上次刷新以来的更改,使其在小更新的大数据集上更高效。动态表的内容与选择的刷新模式无关。

然而,增量刷新可以更有效地利用资源,因为它跳过了对未更改数据的重新处理。使用增量刷新的决策取决于您的工作负载的特征,例如更改的数量和复杂性,以及在速度和资源节省方面的潜在性能提升。

以下部分解释了工作负载适合增量刷新需满足的条件。如果您的工作负载不符合这些部分中描述的条件,请尝试完整刷新模式以提升效率。

有关优化增量刷新性能的信息,请参阅 增量刷新性能

备注

随着时间的推移,随着对增量刷新查询和性能的支持的改进,本文档中的建议可能会发生变化。

了解增量刷新性能

在增量刷新中,大部分工作通常用于计算动态表中的更改。这取决于查询,可能相当复杂。一个常见的误解是增量刷新只扫描源表中的更改,而不是源表本身。这可能导致误解为增量刷新只应执行与更改的源数据量成比例的工作,但事实并非如此。实际上,增量刷新通常需要直接扫描源表。

例如,想象一个查询在表 A 和表 B 之间进行内部联接。如果向表 A 插入一行,它必须与表 B 联接,以计算查询中的更改。表 A 中的这一行可以与表 B 中的许多行联接,这可能意味着即使源中只有少量更改,也会有很多工作。

这种额外的工作可能需要利用各种运算符来完成。增量刷新处理新数据,跳过已经完成的工作。决定跳过什么内容可能需要额外的工作,特别是复杂的查询,不同的运算符可能会以不同的方式跳过工作

通常,变更的大小和局部性会影响可以跳过多少工作。

大小如何影响增量刷新性能

影响增量刷新性能的最重要因素是源数据变更的大小。在确定动态表格刷新更改的大小时,请确保将复制的行包含在内。在微分区中更改了一些行的 DML 也会将该微分区中未更改的行复制到一个新的微分区。

要分析基本表中更改的行数,请在最后一次刷新时在基本表上创建 一个流,并使用 SYSTEM$STREAM_BACKLOG。例如:

CREATE STREAM mystream ON TABLE mybasetable BEFORE(STATEMENT => 'last refresh UUID');
Copy
SELECT * FROM TABLE(SYSTEM$STREAM_BACKLOG('mystream'))
Copy

作为一个极端的例子,考虑从一个源中删除所有数据的影响:完整刷新只看到一个空表,这可以非常快速地处理。与此相比,增量刷新必须处理每一行被删除的记录,这使得它的速度慢得多。

类似的减速也可能发生在不太极端的情况下。良好工作负载的一个良好准则是将源或目标中的变更控制在行数的 5% 以下。

局部性如何影响增量刷新性能

影响增量刷新的第二个最重要因素是 局部性,它是指不同维度上数据或操作的相关程度。

例如,如果您有一个包含时间戳列的表,并且始终在该列中插入包含当前时间的行,那么您的工作负载在插入顺序和时间戳列之间具有很强的局部性。

局部性能够以各种形式显示,但少数形式对于增量刷新特别重要。在以下任一领域改进局部性可提升增量刷新的性能,尽管有时不太可能所有三个类别都具有强局部性。

局部性领域

描述

群集密钥和分区密钥之间的局部性。

在动态表定义中执行分区操作时,根据这些分区密钥对基础源进行群集是有益的。

例如,如果您使用 ID 联接两个表,如果表按其各自的 ID 列进行群集,则对于增量刷新性能更有益。

分区密钥或分组密钥与源变更之间的局部性。

理想情况下,对源的更改应该仅与源表中少量行具有共同的分区密钥。

例如,如果您插入包含当前时间戳的行,由于密钥和源变更之间的强局部性,按小时分组可能会运行良好。但是,如果插入的行包含出现在表中许多其他行中的列值,则按该列分组会导致增量刷新性能较差。

目标表变更和群集之间的局部性。

当增量刷新对动态表应用更改时,更新和删除将与动态表的当前状态进行联接。如果更改与动态表的群集对齐,则此联接的性能更好。

例如,如果刷新仅更新最近插入的行,则它们与表的群集非常一致。

有关 Snowflake 表的存储方式的信息,请参阅 了解 Snowflake 表结构。要管理表上的群集,请使用 自动聚类

单个运算符增量刷新的性能预期

下表显示了单个运算符增量刷新的近似性能预期。性能是相对于完整刷新来衡量的,并且假设只有 5% 的行发生了变更,并且刷新作业至少需要 1 分钟。

备注

由于固定的开销(例如,查询优化、仓库调度和作业清理)不会随着查询优化而加速,短查询(少于 10 秒)可能会看到较小的性能提升。

运算符

性能提升

SELECT

10 倍

WHERE

10 倍

FROM

10 倍

UNION ALL

10 倍

标量汇总

10 倍

对于受局部性影响的运算符,该表显示了具有良好局部性和较差局部性的性能预期。请注意,对于某些运算符来说,较差局部性可能导致比完整刷新更糟糕的性能。

运算符

局部性

性能提升

GROUP BY

良好

5 倍

GROUP BY

较差

1/3 倍

DISTINCT

良好

5 倍

DISTINCT

较差

1/4 倍

OVER

良好

2-5 倍

OVER

较差

1/5 倍

INNER JOIN

良好

10 倍

INNER JOIN

较差

2 倍

OUTER JOIN

良好

3 倍

OUTER JOIN

较差

0.1 倍

有关更多信息,请参阅 运算符如何增量刷新

优化复杂动态表的增量刷新模式性能

动态表通常包含多个运算符,因此难以预测增量刷新的性能。本部分探讨了如何应对这一挑战,并给出了一些增强复杂动态表性能的技巧。

当涉及多个运算符时,增量刷新通过分别处理每个运算符来计算更改,将其变为查询计划的片段,查询计划可以基于其输入计算更改。对于每个输入,此新片段可以在变更之前、变更之后或仅将变更本身请求输入。通过将此过程应用于原始查询中的每个运算符,您将获得一个新的查询计划,该计划将混合使用变更扫描和完整表扫描计算更改。该计划由 Snowflake 的查询优化器优化,并像任何其他查询一样执行。

当增量刷新性能不佳时,通常是因为变更次数太多或局部性较差导致。复杂查询使得识别这些问题变得更加具有挑战性。增量运算符的性能通常取决于变化的数量和输入的局部性。然而,这些输入是其他运算符的输出,因此数据的数量和局部性会随着运算符之间的移动而发生变化。

因此,理解复杂增量刷新性能需要单独考虑每个运算符的输入。以下是一些常见的场景和解决这些问题的建议:

场景

建议

跨多列联接表时,不能同时对所有列使用 CLUSTER BY。

根据频繁变更的密钥优先对较大的表进行群集。例如,在具有大维度表的星级架构中,重点关注维度表的群集。

考虑为同一数据集创建多个副本,每个副本由不同的密钥进行群集,并在相关上下文中使用它们。

您在许多联接上有 GROUP BY 或 OVER。

确保源表通过分组/分区密钥进行群集,并考虑将联接和聚合拆分为两个独立的动态表。

请注意,外部联接与聚合的交互较差。

语言: 中文