使用任务图管理任务依赖关系¶
利用任务图,您可以自动运行一系列任务。任务图或有向无环图 (DAG) 是一系列任务,由单项根任务和多个子任务组成,并根据它们之间的依赖关系进行组织。任务图单向流动,是指一系列任务中后面的任务无法提示先前任务的运行。每项任务可以依赖于多个其他任务,并且只有在所有其他任务完成后才会运行。每项任务还可以有多项依赖于它的子任务。
任务图中的任务还可以使用父任务的返回值,在其 SQL 函数体中执行基于逻辑的操作。
创建任务图¶
要创建任务图,请在创建或更改任务时指定父任务。图表的根任务是指没有父任务的任务。根任务应有明确的时间表来启动任务图的运行。每项子任务必须至少有一个已定义的父任务来链接任务图中的任务。
使用 CREATE TASK ...AFTER 或 ALTER TASK ...ADD AFTER 命令添加子任务。您还可以使用 Python 管理 Snowflake 任务和任务图。有关更多信息,请参阅 使用 Python 管理 Snowflake 任务和任务图。
- 任务图注意事项
一个任务图最多包含 1000 个任务。
单个任务最多可以有 100 个父任务和 100 个子任务。
运行任务图的计算资源必须足够大,方可处理并发任务运行。有关更多信息,请参阅 计算资源。
在以下示例中,根任务提示任务 B 和 C 同时运行。在任务 B 和 C 均运行完毕后,任务 D 会运行。
以下示例展示了在聚合事实数据之前,如何使用任务图更新销售数据库中的维度表:
此示例显示了任务图中的最终任务调用外部函数来触发远程消息传送服务,从而发送通知,告知所有先前的任务均已成功运行完毕。
管理任务图所有权¶
任务图中的所有任务必须具有相同的任务所有者,并且存储在同一数据库和架构中。
您可以通过以下任一操作转移任务图中所有任务的所有权:
使用 DROP ROLE 删除任务图中所有任务的所有者。Snowflake 将所有权转让给运行 DROP ROLE 命令的角色。
针对架构中的所有任务,使用 GRANT OWNERSHIP 转移任务图中所有任务的所有权。
当您使用这些方法转移任务图中任务的所有权时,任务图中的任务将保留彼此之间的关系。
转移单个任务的所有权将切断该任务与任何父任务和子任务之间的依赖关系。有关更多信息,请参阅 断开父任务与子任务的链接 (本主题内容)。
备注
如果任务图的所有者与执行复制的角色不同,则数据库复制不适用于任务图。
运行任务图中的任务¶
任务图运行通过其定义的根任务的运行来启动。成功运行根任务会触发任务图中子任务的级联运行,因为它们的前置任务已完成。根任务可通过以下方式运行:
任务计划 – 通常任务图根据基于 CRON 或间隔的计划运行。
ALTER TASK – 您可以使用
ALTER TASK [ IF EXISTS ] <name> RESUME
来运行基于其现有计划的任务图。首次创建时,必须恢复所有任务。EXECUTE TASK – 您可以使用
EXECUTE TASK <name>
创建任务图的一次性运行。
手动运行任务图中的任务¶
EXECUTE TASK 命令可手动触发单次任务运行,与为任务定义的计划无关。成功运行根任务会触发任务图中子任务的级联运行(基于前置任务的完成),就像根任务按照其定义的计划运行一样。
您还可以使用 EXECUTE TASK <name> RETRY LAST
重新运行任图中的任何子任务。RETRY LAST
尝试从上次失败的任务运行任务图。如果任务成功,所有子任务将继续运行,因为它们的前置任务已完成。
此 SQL 命令非常有用。在允许新的或已修改的任务图在生产环境中执行 SQL 代码之前,此命令可用于对其进行测试。
重叠任务图运行¶
默认情况下,Snowflake 确保一次只允许运行一项特定任务图的一个实例。只有在该任务图中的所有任务都运行完毕后,才会安排根任务的下一次运行。这意味着,如果运行任务图中所有任务所需的累积时间超过了根任务定义中设置的明确计划时间,则至少会跳过任务图的一次运行。该行为由根任务上的 ALLOW_OVERLAPPING_EXECUTION 参数控制;默认值为 FALSE。将参数值设置为 TRUE,允许任务图重叠运行。
此外,只有在子任务的 所有 前置任务均成功完成自己的运行后,子任务才能开始运行。如一项任务会执行耗时的 SQL 操作,则会延迟任何将该任务标识为前置任务的子任务的启动。
在以下示例中,任务图计划在上一次运行尚未完成时开始运行。重叠期(或称为并发时间)以红色标识。该图还确定了每项任务在由用户管理的仓库中运行之前,需要排队的时间跨度。请注意,如果使用无服务器计算资源,则没有排队期:
任务图重叠运行所执行的读/写 SQL 操作不会产生错误或重复的数据时,重叠运行是可以容忍的(甚至是可取的)。但是,对于其他任务图,任务所有者(对任务图中所有任务具有 OWNERSHIP 权限的角色)应为根任务设置适当的计划,并选择适当的仓库大小(或使用无服务器计算资源),以确保在下次计划运行根任务之前完成任务图的一个实例。
为了更好地将任务图与根任务中定义的计划保持一致,请执行以下操作:
如可行,延长根任务运行之间的计划时间。
考虑修改计算密集型任务,以使用无服务器计算资源。如果任务依赖于由用户管理的计算资源,请增加运行任务图中大型或复杂 SQL 语句或存储过程的仓库的大小。
分析每项任务执行的 SQL 语句或存储过程。确定是否可以重写代码,以利用并行处理。
如果以上解决方案都没有帮助,请考虑是否需要对根任务设置 ALLOW_OVERLAPPING_EXECUTION = TRUE,以允许并行运行任务图。可在创建任务时(使用 CREATE TASK)或稍后使用 ALTER TASK 或 Snowsight)来定义此参数。
暂停和恢复任务图中的任务¶
要暂停或恢复任务图中的任务,请使用 ALTER TASK ...RESUME | SUSPEND or the | sf-web-interface|。
- 暂停根任务
根任务暂停时,根任务的所有未来计划运行都将被取消;但如果当前有任何任务正在运行,则这些任务和任何子任务都将继续运行。
- 恢复和暂停子任务
要恢复或暂停子任务,则必须要暂停根任务。恢复已暂停的子任务不需要恢复根任务。
- 以递归方式恢复任务
要以递归方式恢复任务图中的所有任务,请查询 SYSTEM$TASK_DEPENDENTS_ENABLE 函数。
- 运行包含已暂停子任务的任务图
在运行包含一个或多个已暂停子任务的任务图时,此次运行会忽略这些暂停的任务。只要 至少有一个 前置任务处于恢复状态,且所有恢复的前置任务都成功运行完成,具有多个前置任务的子任务即可运行。
任务图版本控制¶
当恢复或手动执行任务图中的根任务时,Snowflake 会设置整个任务图的版本,包括任务图中所有任务的所有属性。暂停和修改任务后,恢复或手动执行根任务时 Snowflake 会设置一个新的版本。
要修改或重新创建任务图中的任何任务,必须先暂停根任务。根任务暂停时,根任务的所有未来计划运行都将被取消;但如果当前有任何任务正在运行,则这些任务和任何子任务都将使用当前版本继续运行。
备注
如果在任务图执行过程中,任务调用的存储过程的定义发生变化,则可以在当前运行的任务调用存储过程时执行新的编程。
例如,假设任务图中的根任务已暂停,但该任务的计划运行已开始。在根任务仍在运行期间,任务图中所有任务的所有者修改了子任务调用的 SQL 代码。子任务使用根任务开始运行时现行的任务图版本,运行并执行其定义中的 SQL 代码。恢复或手动执行根任务时,将设置新版本的任务图。这个新版本包括对子任务的修改。
要检索任务版本的历史记录,请查询 TASK_VERSIONS Account Usage 视图 (在 SNOWFLAKE 共享数据库中)。
任务运行失败后自动暂停任务图¶
可以选择在任务运行连续失败或超时达到指定次数后自动暂停任务图。
在任务图中设置根任务的 SUSPEND_TASK_AFTER_NUM_FAILURES = num
参数。当设置的参数值大于 0
时,任务图中的 任何 子任务连续失败或超时达到指定次数后,根任务将自动暂停。失败或超时的子任务不会暂停。
自动重试失败的任务图运行¶
指定任务图自动重试的次数。如果任何任务图在 FAILED 状态下完成,Snowflake 可以自动从失败的图中的最后一个任务重试任务图。
任务图自动重试功能默认处于禁用状态。要启用此功能,请将 TASK_AUTO_RETRY_ATTEMPTS
设置为大于 0
的值。
断开父任务与子任务的链接¶
可通过以下任何操作来切断任务图中任务之间的依赖关系:
ALTER TASK ...REMOVE AFTER 和 ALTER TASK ...UNSET FINALIZE 解除目标任务与指定父任务或最终根任务之间的关联。
DROP TASK 和 GRANT OWNERSHIP 会切断目标任务的所有关联。例如,根任务 A 有子任务 B,而任务 B 有子任务 C。如果删除任务 B,则任务 A 和 B 之间的关联将被解除,任务 B 和 C 之间的关联也将被解除。
如果上述操作的任意组合切断了子任务与 所有 父任务之间的关联,则子任务将变为独立任务或根任务。
备注
如果将任务的所有权授予其当前所有者,则依赖关系可能不会切断。
查看任务图中的依赖任务¶
要查看根任务的子任务,请查询 TASK_DEPENDENTS 表函数。要在任务图中检索所有任务,请在调用该函数时输入根任务。
您还可以使用 Snowsight 管理和查看您的任务图。有关更多信息,请参阅 查看 Snowsight 中的任务和任务图。
任务图的释放和清理¶
终结器任务用来释放和清理任务图使用的资源。如果执行了任务图,终结器任务必定会运行,并确保在所有场景中执行适当的资源清理并完成必要的步骤。例如,如果任务图运行使用中间表来跟踪需要处理的数据,但在尚未消耗表行的情况下失败,则下一次运行将遇到重复的行并重新处理数据,从而导致执行时间延长或浪费计算资源。终结器任务可以按需删除行或截断表,从而解决此问题。
终结器任务的工作方式与任务图中的其他任何任务很相似,但有以下区别:
终结器任务始终与根任务关联。每个根任务只能有一个终结器任务,一个终结器任务只能与一个根任务相关联。
只有在当前任务图运行中没有其他任务在运行或排队,并且图表中至少有一个任务已开始执行时,才会计划终结器任务。如果跳过图表(例如,跳过根任务),则终结器任务将不会运行。如果 ALLOW_OVERLAPPING_EXECUTION 为 true,则终结器任务的行为将与其他任务类似,即使还有其他进行中的任务图运行,仍会计划终结器任务。
终结器任务不能有任何子任务。任何尝试将终结器任务设为前置任务的命令都将失败。 终结器任务的创建必须包含
FINALIZE
关键字,该关键字与SCHEDULE
和AFTER
关键字均不兼容。
要创建终结器任务,请使用 FINALIZE
关键字创建任务,并设置与根任务的关系:
CREATE TASK <TASK_NAME> ...
... FINALIZE = <ROOT_TASK_NAME>
有关更多信息,请参阅 CREATE TASK。