使用任务图创建任务序列¶
在 Snowflake 中,您可以使用 任务图 管理多个任务,也称为有向无环图 (DAG)。任务图由根任务和从属子任务组成。依赖项必须沿着从开始到结束的方向运行,没有循环。可选最终任务被称为 终结器,可以在所有其他任务完成后执行清理操作。
使用运行时值、图形级配置和父任务的返回值在任务正文中指定基于逻辑的操作,从而构建具有动态行为的任务图。
您可以使用 支持的语言和工具 <label-stored-procedures-handler-languages>`(例如 SQL、JavaScript、Python、Java、Scala 或 Snowflake Scripting),创建任务和任务图。本主题提供 SQL 示例。有关 Python 示例,请参阅 :doc:/developer-guide/snowflake-python-api/snowflake-python-managing-tasks`。
您还可以使用 Snowsight 管理和查看您的任务图。有关更多信息,请参阅 View tasks and task graphs in Snowsight。
创建任务图¶
使用 CREATE TASK 创建根任务,然后使用 CREATE TASK ..AFTER 以选择父任务。
根任务定义 任务图运行时间。子任务按任务图定义的顺序执行。
当多个子任务具有相同的父任务时,子任务将并行运行。
当一个任务有多个父任务时,该任务将等待所有前面的任务成功完成后才启动。(该任务也可能在跳过某些父任务时运行。有关更多信息,请参阅 跳过或挂起子任务)。
以下示例创建无服务器任务图,该图从计划每分钟运行的根任务开始。根任务有两个并行运行的子任务。(该图显示一个示例,其中一个任务比另一个任务运行更长时间。)这两个任务完成后,第三个子任务会运行。终结器任务在所有其他任务完成或无法完成之后运行:
注意事项:
一个任务图最多包含 1000 个任务。
单个任务最多可以有 100 个父任务和 100 个子任务。
当在同一用户管理的仓库上并行运行时,必须调整 计算资源 的大小以处理并发任务运行。
终结器任务¶
您可以添加一个可选的终结器任务,以便在任务图中所有其他任务完成(或无法完成)后运行。使用此任务执行以下操作:
执行清理操作,例如,清理不再需要的中间数据。
发送有关任务成功或失败的通知。
要创建终结器任务,请对根任务使用 CREATETASK ...FINALIZE ...。示例:
注意事项:
终结器任务始终与根任务关联。每个根任务只能有一个终结器任务,一个终结器任务只能与一个根任务相关联。
When the root task of a task graph is skipped (for example, because of overlap task graph runs), the finalizer task won't be started.
终结器任务不能有任何子任务。
仅当当前任务图运行中没有其他任务正在运行或排队时,才会调度终结器任务。
有关更多示例,请参阅 终结器任务示例:发送电子邮件通知 和 终结器任务示例:纠正错误。
管理任务图所有权¶
任务图中的所有任务必须具有相同的任务所有者,并且存储在同一数据库和架构中。
您可以通过以下任一操作转移任务图中所有任务的所有权:
使用 DROP ROLE 删除任务图中所有任务的所有者。Snowflake 将所有权转让给运行 DROP ROLE 命令的角色。
针对架构中的所有任务,使用 GRANT OWNERSHIP 转移任务图中所有任务的所有权。
当您使用这些方法转移任务图中任务的所有权时,任务图中的任务将保留彼此之间的关系。
转移单个任务的所有权将切断该任务与任何父任务和子任务之间的依赖关系。有关更多信息,请参阅 :ref:`label-tasks-graphs-link-sever`(本主题内容)。
备注
如果任务图的所有者与执行复制的角色不同,则数据库复制不适用于任务图。
在任务图中运行或计划任务¶
手动运行任务图¶
您可以运行任务图的单个实例。这有利于在生产中启用任务图之前测试新的或修改的任务图,或者根据需要进行一次性运行。
在启动任务图之前,请对您要在运行中包含的每个子任务(包括可选的终结器任务)使用:doc:ALTER TASK ...RESUME </sql-reference/sql/alter-task>。
要运行任务图的单个实例,请对根任务使用 EXECUTE TASK。运行根任务时,任务图中所有恢复的子任务将按照任务图定义的顺序执行。
按计划或作为触发的任务运行任务¶
在根任务中,定义任务图的运行时间。任务图可以按定期计划运行,也可以由事件触发。有关详细信息,请参阅以下主题:
要启动任务图,您可以执行以下任一操作:
恢复要包含在运行中的每个单独的子任务(包括终结器),然后使用 ALTER TASK ... RESUME。
在根任务上使用 SYSTEM$TASK_DEPENDENTS_ENABLE (<root_task_name>) 同时恢复任务图中的所有任务。
查看任务图中的依赖任务¶
要查看根任务的子任务,请调用 TASK_DEPENDENTS 表函数。要在任务图中检索所有任务,请在调用该函数时输入根任务。
您还可以使用 Snowsight 管理和查看您的任务图。有关更多信息,请参阅 View tasks and task graphs in Snowsight。
修改、挂起或重试任务¶
修改任务图中的任务¶
要修改计划任务图中的任务,请使用 ALTER TASK ... SUSPEND。 如果任务图正在运行,则完成当前运行。根任务的所有未来计划运行都将取消。
当根任务挂起时,子任务(包括终结器任务)保留其状态(挂起、正在运行或已完成)。子任务不需要单独挂起。
挂起根任务后,您可以修改任务图中的任何任务。
要恢复任务图,您可以执行以下任一操作:
使用 ALTER TASK ... RESUME。以前运行的单个子任务不需要恢复。
通过调用 SYSTEM$TASK_DEPENDENTS_ENABLE 并传入根任务的名称,同时恢复任务图中的所有任务。
跳过或挂起子任务¶
要跳过任务图中的子任务,请使用 ALTER TASK ... SUSPEND。
挂起子任务时,任务图会继续运行,好像子任务已成功一样。只要 至少有一个 前置任务处于恢复状态,且所有恢复的前置任务都成功运行完成,具有多个前置任务的子任务即可运行。
重试失败的任务¶
使用 EXECUTE TASK ...RETRY LAST 尝试从上次失败的任务运行任务图。如果任务成功,所有子任务将继续运行,因为它们的前置任务已完成。
自动重试¶
默认情况下,如果子任务失败,则认为整个任务图失败。
您不必等到下一个计划任务图运行,而是可以在根任务上设置 TASK_AUTO_RETRY_ATTEMPTS 参数,指示任务图立即重试。当子任务失败时,立即重试整个任务图,最多重试指定的次数。如果任务图仍未完成,则认为任务图失败。
失败的任务图运行后,挂起任务图¶
默认情况下,任务图在连续失败 10 次后挂起。您可以对根任务设置 SUSPEND_TASK_AFTER_NUM_FAILURES,从而更改此值。
在下面的示例中,每当子任务失败时,任务图会立即重试两次,然后整个任务图才会被视为失败。如果任务图连续三次失败,则任务图将挂起。
断开父任务与子任务的链接¶
可通过以下任何操作来切断任务图中任务之间的依赖关系:
ALTER TASK ...REMOVE AFTER 和 ALTER TASK ...UNSET FINALIZE 解除目标任务与指定父任务或最终根任务之间的关联。
DROP TASK 和 GRANT OWNERSHIP 会切断目标任务的所有关联。例如,根任务 A 有子任务 B,而任务 B 有子任务 C。如果删除任务 B,则任务 A 和 B 之间的关联将被解除,任务 B 和 C 之间的关联也将被解除。
如果上述操作的任意组合切断了子任务与 所有 父任务之间的关联,则子任务将变为独立任务或根任务。
备注
如果将任务的所有权授予其当前所有者,则依赖关系可能不会切断。
Overlap task graph runs¶
默认情况下,Snowflake 确保一次只允许运行一项特定任务图的一个实例。只有在该任务图中的所有任务都运行完毕后,才会安排根任务的下一次运行。这意味着,如果运行任务图中所有任务所需的累积时间超过了根任务定义中设置的明确计划时间,则至少会跳过任务图的一次运行。
To control task graph parallelism, use CREATE TASK or ALTER TASK on the root task to set the OVERLAP_POLICY parameter:
OVERLAP_POLICY = NO_OVERLAP(default): Executes tasks serially with no parallelism. Snowflake schedules the next run of a root task only after all child tasks finish running.OVERLAP_POLICY = ALLOW_CHILD_OVERLAP: Allows child task parallelism. When the next scheduled run time for the root task occurs while any child task is still running, Snowflake starts a new instance of the task graph. Root tasks never overlap with this policy.OVERLAP_POLICY = ALLOW_ALL_OVERLAP: Allows unlimited true parallelism. Snowflake can run multiple instances of the entire task graph, including the root task, concurrently.
任务图重叠运行所执行的读/写 SQL 操作不会产生错误或重复的数据时,重叠运行是可以容忍的(甚至是可取的)。但是,对于其他任务图,任务所有者(对任务图中所有任务具有 OWNERSHIP 权限的角色)应为根任务设置适当的计划,并选择适当的仓库大小(或使用无服务器计算资源),以确保在下次计划运行根任务之前完成任务图的一个实例。
为了更好地将任务图与根任务中定义的计划保持一致,请执行以下操作:
如可行,延长根任务运行之间的计划时间。
考虑修改计算密集型任务,以使用无服务器计算资源。如果任务依赖于由用户管理的计算资源,请增加运行任务图中大型或复杂 SQL 语句或存储过程的仓库的大小。
分析每项任务执行的 SQL 语句或存储过程。确定是否可以重写代码,以利用并行处理。
If none of the above solutions help, consider whether it is necessary to allow concurrent runs of the task graph by setting OVERLAP_POLICY = ALLOW_CHILD_OVERLAP or OVERLAP_POLICY = ALLOW_ALL_OVERLAP on the root task. You can set this parameter when you create a task (using CREATE TASK) or later (using ALTER TASK or in Snowsight).
版本控制¶
当恢复或手动执行任务图中的根任务时,Snowflake 会设置整个任务图的版本,包括任务图中所有任务的所有属性。暂停和修改任务后,恢复或手动执行根任务时 Snowflake 会设置一个新的版本。
要修改或重新创建任务图中的任何任务,必须先暂停根任务。根任务暂停时,根任务的所有未来计划运行都将被取消;但如果当前有任何任务正在运行,则这些任务和任何子任务都将使用当前版本继续运行。
备注
如果在任务图执行过程中,任务调用的存储过程的定义发生变化,则可以在当前运行的任务调用存储过程时执行新的编程。
例如,假设任务图中的根任务已暂停,但该任务的计划运行已开始。在根任务仍在运行期间,任务图中所有任务的所有者修改了子任务调用的 SQL 代码。子任务使用根任务开始运行时现行的任务图版本,运行并执行其定义中的 SQL 代码。恢复或手动执行根任务时,将设置新版本的任务图。这个新版本包括对子任务的修改。
要检索任务版本的历史记录,请查询 TASK_VERSIONS Account Usage 视图 (在 SNOWFLAKE 共享数据库中)。
任务图持续时间¶
任务图持续时间包括从根任务计划开始到最后一个子任务完成的时间。要计算任务图的持续时间,请查询 COMPLETE_TASK_GRAPHS 视图 并比较 SCHEDULED_TIME 与 COMPLETED_TIME。
例如,下图显示了计划每分钟运行的任务图。根任务及其两个子任务各排队 5 秒并运行 10 秒,总共需要 45 秒才能完成。
任务图超时¶
在根任务中设置 USER_TASK_TIMEOUT_MS 时,超时适用于整个任务图。
在子任务或终结器任务中设置 USER_TASK_TIMEOUT_MS 时,超时仅适用于该任务。
在根任务和子任务中都设置 USER_TASK_TIMEOUT_MS 时,子任务超时将覆盖该子任务的根任务超时。
注意事项¶
对于无服务器任务,Snowflake 会自动缩放资源,以确保任务在目标完成间隔(包括排队时间)内完成。
对于用户管理任务,当任务计划在共享或繁忙仓库上运行时,较长的排队时间很常见。
对于任务图,总时间可能包括子任务等待其前置任务完成的额外排队时间。
创建具有逻辑(运行时信息、配置和返回值)的任务图¶
任务图中的任务使用父任务的返回值,在其函数体中执行基于逻辑的操作。
注意事项:
一些基于逻辑的命令(如 SYSTEM$GET_PREDECESSOR_RETURN_VALUE)区分大小写。但是,使用不带引号的 CREATE TASK 创建的任务 以大写存储和解析。要对此进行管理,您可以执行以下任一操作:
仅使用大写字母创建任务名称。
命名和调用任务时使用引号。
对于使用小写字符定义的任务名称,请使用大写字符调用任务。例如:由“CREATE TASK task_c...”定义的任务可以 SELECT SYSTEM$GET_PREDECESSOR_RETURN_VALUE('TASK_C') 形式调用。
将配置信息传递给任务图¶
You can pass configuration information by using a JSON object that can be read by other tasks in a task graph. Use the syntax CREATE TASK or ALTER TASK with the CONFIG parameter to set, unset, or modify the configuration information in the root task. Use the function SYSTEM$GET_TASK_GRAPH_CONFIG to retrieve the configuration information.
Example:
备注
You can dynamically override the configuration for a single task execution with the EXECUTE TASK ... USING CONFIG command. With this command, you can test different configurations or run ad-hoc executions with modified settings without changing the task definition.
在任务之间传递返回值¶
您可以在任务图中的任务之间传递返回值。使用函数 SYSTEM$SET_RETURN_VALUE 从任务中添加返回值,并使用函数 SYSTEM$GET_PREDECESSOR_RETURN_VALUE 检索返回值。
当一个任务有多个前置任务时,您必须指定哪个任务具有您想要的返回值。在下面的示例中,我们在添加配置信息的任务图中创建根任务。
获取和使用运行时信息¶
使用函数 SYSTEM$TASK_RUNTIME_INFO 报告有关当前任务运行的信息。该函数有几个特定于任务图的选项。例如,使用 CURRENT_ROOT_TASK_NAME 获取当前任务图中根任务的名称。以下示例展示了如何根据任务图的根任务开始的时间向表中添加日期戳。
示例¶
示例:启动多个任务并报告状态¶
在以下示例中,根任务启动更新三个不同表的任务。在这三个表更新后,一个任务会将其他三个表中的信息合并到一个汇总销售表中。
终结器任务示例:发送电子邮件通知¶
此示例演示如何使用终结器任务发送任务图运行的电子邮件摘要。终结器任务调用两个外部函数:一个汇总每项任务的完成状态,另一个将信息格式化为电子邮件以供远程消息服务使用。
此示例使用名为 task_root 的示例根任务和名为 notify_finalizer 的示例终结器任务。
终结器任务示例:纠正错误¶
此示例演示了终结器任务如何更正错误。
出于演示目的,这些任务设计为在首次运行时失败。终结器任务更正问题并重新启动任务,这将在以下运行中成功: