分区写入
示例
将表写入 Hive 分区的 Parquet 数据集:
COPY orders TO 'orders'
(FORMAT parquet, PARTITION_BY (year, month));
将表写入 Hive 分区的 CSV 数据集,并允许覆盖:
COPY orders TO 'orders'
(FORMAT csv, PARTITION_BY (year, month), OVERWRITE_OR_IGNORE);
将表写入 Hive 分区的 GZIP 压缩 CSV 数据集,并显式指定数据文件扩展名:
COPY orders TO 'orders'
(FORMAT csv, PARTITION_BY (year, month), COMPRESSION gzip, FILE_EXTENSION 'csv.gz');
分区写入
当在 COPY 语句中指定 PARTITION_BY 子句时,文件会按 Hive 分区目录层级写出。目标路径是根目录名称(上例中为 orders)。文件会按层级写入目录结构。当前实现中,每个目录每个线程会写出一个文件。
orders
├── year=2021
│ ├── month=1
│ │ ├── data_1.parquet
│ │ └── data_2.parquet
│ └── month=2
│ └── data_1.parquet
└── year=2022
├── month=11
│ ├── data_1.parquet
│ └── data_2.parquet
└── month=12
└── data_1.parquet
分区值会自动从数据中提取。需要注意,分区数量过多时会生成大量文件,写入成本可能很高。理想分区数取决于数据集规模。
若要限制使用 PARTITION_BY 写入时、flush 到磁盘前系统可同时保持打开的最大文件数,请使用配置项 partitioned_write_max_open_files(默认 100):
SET partitioned_write_max_open_files = 10;
最佳实践:将数据写入大量小分区成本较高。通常建议每个分区至少有
100 MB数据。
文件名模式
默认文件名为 data_0.parquet 或 data_0.csv。通过 FILENAME_PATTERN 可定义包含 {i} 或 {uuid} 的模式,以生成指定文件名:
{i}会被索引值替换。{uuid}会被一个 128 位 UUID 替换。
将表写入 Hive 分区的 .parquet 数据集,并在文件名中使用索引:
COPY orders TO 'orders'
(FORMAT parquet, PARTITION_BY (year, month), OVERWRITE_OR_IGNORE, FILENAME_PATTERN 'orders_{i}');
将表写入 Hive 分区的 .parquet 数据集,并使用唯一文件名:
COPY orders TO 'orders'
(FORMAT parquet, PARTITION_BY (year, month), OVERWRITE_OR_IGNORE, FILENAME_PATTERN 'file_{uuid}');
覆盖写入
默认情况下,分区写入不允许覆盖已有目录。
在本地文件系统上,OVERWRITE 与 OVERWRITE_OR_IGNORE 会删除已有目录。
在远程文件系统上,不支持覆盖写入。
追加写入
若要向已有 Hive 分区目录结构追加数据,请使用 APPEND 选项:
COPY orders TO 'orders'
(FORMAT parquet, PARTITION_BY (year, month), APPEND);
使用 APPEND 的行为与 OVERWRITE_OR_IGNORE, FILENAME_PATTERN '{uuid}' 类似,
但 Goose 会额外检查文件是否已存在;若极少数情况下发生冲突,会重新生成 UUID(避免重名)。
处理列名中的斜杠
若列名中包含斜杠,请使用 url_encode 函数 实现的百分号编码(Percent-Encoding)进行处理。