加载数据¶
本主题提供加载暂存数据的最佳实践、一般准则和重要注意事项。
本主题内容:
用于选择暂存数据文件的选项¶
COPY 命令支持用于从暂存区加载数据文件的多个选项:
按路径(内部暂存区)/前缀(Amazon S3 桶)。有关信息,请参阅 按路径组织数据。
指定要加载的特定文件的列表。
使用模式匹配按模式识别特定文件。
通过这些选项,您可以使用单个命令将一部分暂存数据复制到 Snowflake 中。这允许您利用并行操作来执行与文件子集匹配的并发 COPY 语句。
文件列表¶
COPY INTO <table> 命令包含一个 FILES 参数,用于按特定名称加载文件。
小技巧
在用于识别/指定要从暂存区加载的数据文件的三个选项中,提供离散的文件列表通常是最快的;但是,FILES 参数最多支持 1000 个文件,这意味着使用 FILES 参数执行的 COPY 命令最多只能加载 1000 个文件。
例如:
COPY INTO load1 FROM @%load1/data1/ FILES=('test1.csv', 'test2.csv', 'test3.csv')
文件列表可以与路径相结合,以进一步控制数据加载。
模式匹配¶
COPY INTO <table> 命令包含一个 PATTERN 参数,用于使用正则表达式加载文件。
例如:
COPY INTO people_data FROM @%people_data/data1/ PATTERN='.*person_data[^0-9{1,3}$$].csv';
使用正则表达式的模式匹配通常是用于识别/指定要从暂存区加载的数据文件的三个选项中最慢的;但是,如果您从外部应用程序按命名顺序导出文件,并且希望以相同的顺序批量加载文件,则此选项非常有效。
模式匹配可以与路径相结合,以进一步控制数据加载。
备注
正则表达式应用于批量数据加载与 Snowpipe 数据加载的方式不同。
Snowpipe 从存储位置修剪暂存区定义中的任何路径段,并将正则表达式应用于任何剩余的路径段和文件名。要查看暂存区定义,请执行针对暂存区的 DESCRIBE STAGE 命令。URL 属性由桶或容器名称以及零个或多个路径段组成。例如,如果 FROM 位置位于 COPY INTO <table> statement is
@s/path1/path2/
and the URL value for stage@s
iss3://mybucket/path1/
, then Snowpipe trims/path1/
from the storage location in the FROM clause and applies the regular expression topath2/
中,加上路径中的文件名。批量数据加载操作将正则表达式应用于 FROM 子句中的整个存储位置。
Snowflake 建议您为 Snowpipe 启用云事件筛选,以降低成本、事件噪音和延迟。仅当云提供商的事件筛选功能不足时,才使用 PATTERN 选项。有关为每个云提供商配置事件筛选的更多信息,请参阅以下页面:
使用对象键名称筛选配置事件通知 – Amazon S3 (https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-filtering.html)
了解事件网格订阅的事件筛选 – Azure (https://docs.microsoft.com/en-us/azure/event-grid/event-filtering)
筛选消息 – Google Pub/Sub (https://cloud.google.com/pubsub/docs/filtering)
执行引用相同数据文件的并行 COPY 语句¶
执行 COPY 语句时,Snowflake 会在语句中引用的数据文件的表元数据中设置加载状态。这样可以防止并行 COPY 语句将相同的文件加载到表中,从而避免数据重复。
COPY 语句处理完成后,Snowflake 会根据需要调整数据文件的加载状态。如果一个或多个数据文件无法加载,Snowflake 会将这些文件的加载状态设置为加载失败。这些文件可用于要加载的后续 COPY 语句。
加载较旧的文件¶
本部分介绍 COPY INTO <table> 命令如何根据文件的加载状态是已知还是未知来防止数据重复。如果使用按日期的逻辑粒度路径将数据分区存储在暂存区(如 按路径组织数据 中的建议),并在暂存数据后的短时间内加载数据,则此部分在很大程度上不适用于您。但是,如果 COPY 命令跳过数据加载中的旧文件(即历史数据文件),则本部分将介绍如何绕过默认行为。
加载元数据¶
Snowflake 维护加载数据的每个表的详细元数据,包括:
从中加载数据的每个文件的名称
文件大小
文件的 ETag
文件中解析的行数
文件上次加载的时间戳
有关加载过程中文件中遇到的任何错误的信息
此加载元数据将在 64 天后过期。如果暂存数据文件的 LAST_MODIFIED 日期距今不超过 64 天,则 COPY 命令可以确定给定表的加载状态并防止重新加载(和数据重复)。LAST_MODIFIED 日期是文件最初暂存或上次修改时的时间戳,以较晚者为准。
如果 LAST_MODIFIED 日期距今超过 64 天,则如果以下 任一 事件的发生日期距当前日期不超过 64 天,则加载状态仍为已知:
文件已成功加载。
表的初始数据集(即创建表后的第一批数据)已加载。
但是,如果 LAST_MODIFIED 日期距今超过 64 天,并且 初始数据集在 64 天前加载到表中(以及 如果文件加载到表中,则也发生在 64 天之前),则 COPY 命令无法确定文件是否已加载。在这种情况下,为了防止意外重新加载,该命令默认跳过该文件。
解决方法¶
若要加载元数据已过期的文件,请将 LOAD_UNCERTAIN_FILES 复制选项设置为 true。复制选项引用加载元数据(如果可用)以避免数据重复,但也会尝试加载具有过期加载元数据的文件。
或者,设置 FORCE 选项以加载所有文件,忽略加载元数据(如果存在)。请注意,此选项会重新加载文件,可能会复制表中的数据。
示例¶
在此示例中:
表在 1 月 1 日 创建,初始表加载在同一天发生。
64 天过去了。在 3 月 7 日,加载元数据将过期。
文件将分别于 7 月 27 日 和 28 日 暂存并加载到表中。由于文件是在加载前一天暂存的,因此 LAST_MODIFIED 日期在 64 天内。加载状态是已知的。该文件没有数据或格式问题,并且 COPY 命令已成功加载该文件。
64 天过去了。在 9 月 28 日,暂存文件的 LAST_MODIFIED 日期超过 64 天。在 9 月 29 日,成功加载文件的加载元数据将过期。
尝试在 11 月 1 日 将文件重新加载到同一表中。由于 COPY 命令无法确定文件是否已加载,因此将跳过该文件。加载文件需要 LOAD_UNCERTAIN_FILES 复制选项(或 FORCE 复制选项)。
在此示例中:
文件在 1 月 1 日 暂存。
64 天过去了。在 3 月 7 日,暂存文件的 LAST_MODIFIED 日期超过 64 天。
在 9 月 29 日 创建一个新表,并将暂存文件加载到该表中。由于初始表加载发生在不到 64 天前,因此 COPY 命令可以确定文件尚未加载。该文件没有数据或格式问题,并且 COPY 命令已成功加载该文件。
JSON 数据:移除“null”值¶
在 VARIANT 列中,NULL 值存储为包含单词“null”的字符串,而不是 SQL NULL 值。如果 JSON 文档中的“null”值表示缺少值并且没有其他特殊含义,我们建议在加载 JSON 文件时将 COPY INTO <table> 命令的文件格式选项 STRIP_NULL_VALUES 设置为 TRUE。保留“null”值通常会浪费存储空间并减慢查询处理速度。
CSV 数据:修剪前导空格¶
如果外部软件导出用引号括起来的字段,但在每个字段的开始引号字符之前插入一个前导空格,则 Snowflake 会读取前导空格而不是开始引号字符作为字段的开头。引号字符被解释为字符串数据。
可使用 TRIM_SPACE 文件格式 选项在数据加载期间移除不需要的空格。
例如,示例 CSV 文件中的以下每个字段都包含一个前导空格:
"value1", "value2", "value3"
以下 COPY 命令修剪前导空格并移除每个字段的引号:
COPY INTO mytable
FROM @%mytable
FILE_FORMAT = (TYPE = CSV TRIM_SPACE=true FIELD_OPTIONALLY_ENCLOSED_BY = '0x22');
SELECT * FROM mytable;
+--------+--------+--------+
| col1 | col2 | col3 |
+--------+--------+--------+
| value1 | value2 | value3 |
+--------+--------+--------+