克隆注意事项¶
本主题介绍在 Snowflake 中克隆对象(特别是数据库、架构和非临时表)时的重要注意事项。DDL 和 DML 事务(源对象上)、Time Travel 和数据保留期等因素可能会影响对象克隆。
本主题内容:
所克隆对象的访问控制权限¶
如果源对象是数据库或架构,则克隆将继承对源对象中包含的所有子对象克隆授予的 所有 权限:
对于数据库,包含的对象包括架构、表、视图等。
对于架构,包含的对象包括表、视图等。
请注意,容器本身(数据库或架构)的克隆不会继承对源容器授予的权限。
大多数对象的 CREATE <object> ... CLONE 语句 不会 将源对象的授权复制到对象克隆。但是,支持 COPY GRANTS 子句的 CREATE <object> 命令(例如 CREATE TABLE、CREATE VIEW)可以选择将授权复制到对象克隆。例如,CREATE TABLE ...CLONE 命令语法支持 COPY GRANTS 参数。在 CREATE TABLE 语句中指定 COPY GRANTS 参数时,创建操作会将所有权限(除 OWNERSHIP 外)从源表复制到新表。同样的行为也适用于其他支持 COPY GRANTS 子句的 CREATE 命令。
在其他情况下,必须向新创建的克隆授予所有必需的权限(使用 GRANT <privileges>)。
克隆和 Snowflake 对象¶
本节介绍有关特定 Snowflake 对象的特殊克隆注意事项。
克隆和托管访问架构¶
如果克隆架构并指定 WITH MANAGED ACCESS 子句,所需的权限取决于源架构是托管架构还是非托管架构。有关详细信息,请参阅 CREATE SCHEMA 权限。
克隆和对象参数¶
克隆的对象继承克隆该对象时在源对象上设置的对象参数。如果可以在对象容器(即账户、数据库、架构)上设置对象参数,并且未在源对象上明确设置对象参数,则对象克隆将继承默认参数值或在最低级别覆盖的值。有关对象参数的更多信息,请参阅 参数。
克隆和默认序列¶
在表中,列可以引用生成默认值的 序列。克隆表时,克隆的表引用源序列或克隆序列:
如果克隆了同时包含表和序列的数据库或架构,则克隆的表将引用克隆的序列。
否则,克隆的表将引用源序列。
例如,如果序列是在不同的数据库或架构中定义的,则克隆表将引用源序列。或者,如果只克隆表本身,则克隆的表将引用源序列。
如果您不希望新表继续使用源序列,请运行以下命令:
ALTER TABLE <table_name> ALTER COLUMN <column_name> SET DEFAULT <new_sequence>.nextval;
克隆和外键约束¶
表可以具有引用包含主键的表的外键约束。当克隆带有外键约束的表时,克隆表会引用包含主键的源表或克隆表:
如果克隆了包含两个表的数据库或架构,则带有外键的克隆表将引用其他克隆表中的主键。
如果表位于不同的数据库或架构中,则克隆表将引用源表中的主键。
克隆和群集密钥¶
表可以将列的子集指定为 群集密钥,以便将相似的行放在同一个微分区中。克隆带有群集密钥的表时,将使用群集密钥创建新表。默认情况下,自动聚类 在新表中处于暂停状态。要恢复新表的自动群集,请运行以下命令:
ALTER TABLE <name> RESUME RECLUSTER
克隆和暂存区¶
可以克隆单个外部指定的暂存区。外部暂存区引用外部云存储中的桶或容器;克隆外部暂存区对引用的云存储没有影响。
无法 克隆内部(即 Snowflake)指定的暂存区。
克隆数据库或架构时:
克隆操作开始后,会对源中存在的外部指定的暂存区进行克隆。
克隆操作会对表进行克隆,这意味着也会对与每个表关联的内部暂存区进行克隆。源数据库或架构的表暂存区中存在的数据文件都不会复制到克隆中(即克隆的表暂存区为空)。
内部指定的暂存区 未 进行克隆。
克隆和事件表¶
克隆事件表时,只能在事件表之间克隆。换言之,不能从常规表克隆到事件表,也不能从事件表克隆到常规表。
克隆和管道¶
克隆数据库或架构时,不会 克隆源容器中引用内部(即 Snowflake)暂存区的管道。
但是,引用外部暂存区的管道会进行克隆。其中包括设置了 INTEGRATION 参数的管道对象。此参数指向通知集成,以启用在从 Google Cloud Storage 或 Azure blob 存储中的文件加载数据时自动引入 Snowpipe。
在暂存区位置(例如 blob 存储容器)中创建数据文件时,通知的副本会发送到与暂存区位置匹配的每个管道。这会导致以下行为:
如果在管道定义中的 COPY 语句里,表是完全限定的(以
db_name.schema_name.table_name
或schema_name.table_name
的形式),则 Snowpipe 会将每个管道的重复数据加载到源表(即 COPY 语句中的database.schema.table
)中。如果管道定义中表 未 完全限定,则 Snowpipe 会将数据加载到源和克隆数据库/架构的表(例如
mytable
)中。
管道克隆的默认状态如下所示:
如果显示
AUTO_INGEST = FALSE
,则克隆的管道默认处于暂停状态。如果显示
AUTO_INGEST = TRUE
,则克隆的管道已设置为STOPPED_CLONED
状态。在此状态下,管道不会因为新暂存文件而累积事件通知。当管道显式恢复时,它仅处理因新事件通知而触发的数据文件。
各种状态下的管道克隆都可以恢复,方法是执行 ALTER PIPE ... RESUME 语句。
克隆和流¶
当前,在克隆包含源表和 Streams 的数据库或架构时,无法访问 Streams 中(克隆中)未使用的记录。此行为与表的 Time Travel 一致。如果克隆了表,则表克隆的历史数据将从创建克隆的时间/点开始。
克隆和任务¶
当克隆包含任务的数据库或架构时,克隆中的任务默认处于暂停状态。任务可以单独恢复(使用 ALTER TASK ... RESUME)。
克隆和警报¶
克隆包含警报的数据库或架构时,克隆中的警报默认处于 暂停 状态。
要恢复暂停的警报,可以使用 ALTER ALERT ...RESUME 命令。
克隆和治理对象¶
掩码和行访问策略
在访问克隆的对象时,以下方法有助于保护数据免受具有表或视图 SELECT 权限的用户的侵害:
不支持克隆单个策略对象。
克隆架构会导致克隆该架构中的所有策略。
克隆的表会映射到与源表相同的策略。换句话说,如果在基表或其列上设置了策略,则该策略将附加到克隆的表或其列中。
当表在其父架构克隆的上下文中进行克隆时,如果源表引用了同一父架构中的策略(即本地引用),则克隆的表将引用克隆的策略。
如果源表引用了不同架构中的策略(即外部引用),则克隆表会保留外部引用。
有关更多信息,请参阅 CREATE <object> ... CLONE。
另请参阅:
标签:
源对象(例如表)中的标签关联保存在克隆的对象中。
对于数据库或架构:
也会克隆存储在该数据库或架构中的标签。
克隆数据库或架构时,也会克隆保留在该架构或数据库中的标签。
如果表或视图存在于源架构/数据库中,并且引用了同一架构或数据库中的标签,则克隆的表或视图将映射到相应的克隆标签(在目标架构/数据库中),而不是源架构或数据库中的标签。
基于标签的掩码策略:
对于基于标签的掩码策略,如果标签存储在与掩码策略和表不同的架构中,克隆包含掩码策略和表的架构,会导致克隆的表受源架构中的掩码策略的保护,而不是受克隆架构中的掩码策略的保护。
但是,对于标签、掩码策略和表全部存在于架构中的基于标签的掩码,克隆架构会导致表受克隆架构中的掩码策略的保护,而不是受源架构中的掩码策略的保护。
如果对表进行克隆,或将表移至其他架构或数据库,并且该表最初受架构或数据库上设置的基于标签的掩码策略的保护,则该表将不受在源架构或数据库上设置的基于标签的掩码策略的保护。如果目标架构或数据库上设置了基于标签的掩码策略,则该表将受到在目标架构或数据库上设置的基于标签的掩码策略的保护。
克隆和数据库角色¶
如果目标数据库中尚不存在数据库角色,可以使用 CREATE DATABASE ROLE ...CLONE 命令克隆数据库角色。有关详细信息,请参阅 CREATE <object> ... CLONE。
克隆和 Java UDFs¶
当克隆包含 Java UDF 的数据库或架构时,可以克隆 Java UDF。Java UDF 必须满足某些条件才能被克隆。有关更多信息,请参阅 克隆的限制。
DDL 对克隆的影响¶
克隆速度很快,但不是即时的,特别是对于大型对象(例如表)。因此,如果在进行克隆操作期间对源对象执行 DDL 语句(例如重命名架构中的表),则克隆中可能无法显示更改。这是因为 DDL 语句是原子的,不是多语句事务的一部分。
此外,Snowflake 不会记录克隆操作开始时存在哪些对象名称,以及哪些名称已更改。因此,重命名(或删除并重新创建)源子对象的 DDL 语句会与正在进行的克隆操作竞争,并可能导致名称冲突。
在以下示例中,在克隆父数据库时,删除了 t_sales
表,修改了另一个表并赋予它与删除的表相同的名称,因此产生错误:
CREATE OR REPLACE DATABASE staging_sales CLONE sales; DROP TABLE sales.public.t_sales; ALTER TABLE sales.public.t_sales_20170522 RENAME TO sales.public.t_sales; 002002 (42710): None: SQL compilation error: Object 'T_SALES' already exists.
小技巧
为避免在克隆操作期间出现名称解析冲突,建议在克隆完成之前,不要将对象重命名为已删除对象以前使用的名称。
DML 和数据保留对克隆的影响¶
数据保留期 指定 Snowflake 保留历史数据的天数,以便对对象执行 Time Travel 操作。由于为 Time Travel 保留的数据会在表级别产生存储成本,因此一些用户将某些表的此参数设置为 0
,这实际上禁用了这些表的数据保留功能(即,当该值设置为 0
时,将清除为 DML 事务保留的 Time Travel 数据,产生的额外存储成本可以忽略不计)。
克隆操作需要时间才能完成,尤其是对于大型表而言。在此期间,DML 事务可以更改源表中的数据。随后,Snowflake 尝试克隆操作开始时存在的表数据。但是,如果已为克隆期间发生的 DML 事务清除数据(因为表的保留时间为 0
),则数据将无法完成操作,从而产生类似于以下内容的错误:
ProgrammingError occured: "000707 (02000): None: Data is not available." with query id None
小技巧
作为解决方法,建议在克隆对象时遵循以下 任一 最佳实践:
如果可能,在克隆操作完成之前,不要对源对象(或其任何子对象)执行 DML 事务。
如果无法做到这一点,则在开始克隆之前,为架构(如果要克隆整个数据库,则为数据库)中的所有表设置
DATA_RETENTION_TIME_IN_DAYS=1
。操作完成后,如果需要,请记住将源中那些表的参数值重置为0
。您可能还需要将克隆表的值设置为
0
(如果您计划对克隆表进行 DML 更改,并且不希望为表上的 Time Travel 产生额外的存储费用)。
使用 Time Travel 进行克隆(仅限数据库、架构、表、动态表、事件表和流)¶
本节提供使用 Time Travel 克隆过去特定时间/点的对象时,需要考虑的信息。
克隆历史对象¶
如果在 AT | BEFORE 子句中设置的时间/点上,源对象不存在,则会返回错误。
在以下示例中,CREATE TABLE ... CLONE 语句尝试克隆过去(30 分钟前)不存在的某个时间点的源表:
CREATE TABLE t_sales (numeric integer) data_retention_time_in_days=1; CREATE OR REPLACE TABLE sales.public.t_sales_20170522 CLONE sales.public.t_sales at(offset => -60*30); 002003 (02000): SQL compilation error: Object 'SALES.PUBLIC.T_SALES' does not exist.
在克隆的数据库或架构中,在指定时间/点不存在的 子 对象都无法克隆。
在以下情况下,克隆操作会失败:
如果指定的 Time Travel 时间超过了克隆数据库或架构的 当前子级 的保留时间。
作为已从 Time Travel 中清除的子对象的解决方法,请使用 IGNORE TABLES WITH INSUFFICIENT DATA RETENTION 参数,该参数属于 CREATE <object> ...CLONE 命令。有关更多信息,请参阅 子对象和数据保留时间。
如果在 AT | BEFORE 子句中指定的时间点之后,(使用 CREATE OR REPLACE PIPE 语法)重新创建或删除了设置为
AUTO-INGEST = TRUE
的管道对象。此限制不适用于使用 REST API(即使用AUTO-INGEST = FALSE
)为 Snowpipe 手动引入而创建的管道对象。
子对象和数据保留时间¶
如果子对象(例如,表)的 数据保留期 比其父对象(例如,数据库或架构)的数据保留期短,子对象的历史数据将移出 Time Travel,然后再将其父对象的历史数据移出 Time Travel。
例如,数据库 db1
的 数据保留期 是七天,而 db1
中表 t1
的数据保留期是一天。如果在过去 12 小时的某个时间点使用 Time Travel 克隆 db1
,克隆操作成功创建了 db1
的克隆,其中包含克隆的表 t1
。
但是,如果您尝试在过去两天的某个时间点克隆 db1
,在该时间点表 t1
的历史数据在 Time Travel 中不再可用,克隆操作失败。
作为一种解决方法,请使用 CREATE <object> ... CLONE 命令的 IGNORE TABLES WITH INSUFFICIENT DATA RETENTION 参数克隆数据库或架构。该参数将跳过在为克隆操作指定的时间,Time Travel 中不再具有可用历史数据的表。
克隆历史对象元数据¶
对象克隆使用 Time Travel,可以继承执行 CREATE <object> ... CLONE 语句时源对象当前的 名称 和 结构,或者过去指定时间/点源对象的名称和结构。无论是否使用 Time Travel,对象克隆都会继承执行语句时源对象当前的其他元数据,例如注释或表群集密钥。
备注
为确保长时间克隆操作中的行为一致,当没有为 CREATE <object> ... CLONE 语句指定 AT 或 BEFORE 子句时,克隆操作在内部设置 AT 子句值作为启动语句时的时间戳。