Iceberg 写入时优化

1. 行级更新时,Merge into减少 I/O

基本区别

INSERT OVERWRITE
  • 功能:将整个表或分区内的数据替换为新的数据集。
  • 操作方式:重写目标分区内的所有文件,即使只对部分数据更新,需要重写所有文件。
  • 开销:重写大量数据文件会导致高 I/O 开销和时间消耗,对大规模数据集不友好。
MERGE INTO
  • 功能:根据条件从源数据集更新、插入或删除目标表中的数据。
  • 操作方式:仅对满足条件的数据行进行更新或插入,其他数据不受影响。
  • 开销:只对部分数据行操作,降低 I/O 和计算开销,更加高效。

示例对比

INSERT OVERWRITE 示例
INSERT OVERWRITE TABLE target_table
SELECT * FROM (
  SELECT *,
         ROW_NUMBER() OVER (PARTITION BY key_column ORDER BY update_time_column DESC) AS row_num
   FROM source_table
) tmp
WHERE row_num = 1
UNION ALL
SELECT * FROM target_table t
WHERE NOT EXISTS (
  SELECT 1 FROM source_table s WHERE t.key_column = s.key_column
);

该示例会重写整个 target_table

MERGE INTO 示例
MERGE INTO target_table AS t
USING (
    SELECT *, 
           ROW_NUMBER() OVER (PARTITION BY key_column ORDER BY update_time_column DESC) AS row_num
    FROM source_table
) AS s
ON t.key_column = s.key_column
WHEN MATCHED AND s.row_num = 1 THEN
  UPDATE SET t.column1 = s.column1, 
             t.column2 = s.column2, 
             t.update_time_column = s.update_time_column
WHEN NOT MATCHED THEN
  INSERT (key_column, column1, column2, update_time_column)
  VALUES (s.key_column, s.column1, s.column2, s.update_time_column);

MERGE INTO 提供增量更新,适用于流批一体场景,减少变更数据量,避免积压。


2. Distribute

1. 减少小文件

  • 适用于 Iceberg 扩展语法,按分区减少小文件写入。
ALTER TABLE prod.db.sample WRITE DISTRIBUTED BY PARTITION;

与手动修改 write.distribution-mode=hash 的效果相同。

ALTER TABLE prod.db.sample SET TBLPROPERTIES (
    'write.distribution-mode'='hash'
);

2. Spark Append、Overwrite

  • Spark 的 insert intoinsert overwrite 可以手动进行分布。
INSERT OVERWRITE TABLE target_table 
SELECT * FROM source_table 
DISTRIBUTE BY date;

解决数据倾斜:

INSERT OVERWRITE TABLE target_table 
SELECT * FROM source_table 
DISTRIBUTE BY date, CAST(RAND()*N AS INT);
分区为多级
  • 如果分区为多级(如 PARTITIONED BY date, type),直接选择分区:date, type
分区为一级
  • 针对一级分区(如只有时间分区 date),添加随机值:
DISTRIBUTE BY {表分区列}, CAST(RAND()*N AS INT);

建议 N = 数据量 / 256MB,也就是一个文件256M左右。


3. 排序写入(Order By)

全局排序

  • 使用 DDL 设置表的 ordered,配置后写入时会全局排序。
ALTER TABLE prod.db.sample WRITE ORDERED BY category, id;

其他排序选项

  • 可以指定排序方向和 NULL 排序:
ALTER TABLE prod.db.sample WRITE ORDERED BY category ASC, id DESC;
ALTER TABLE prod.db.sample WRITE UNORDERED;

数据影响

  • 设置 WRITE ORDERED BY 仅影响新写入数据的布局,不会对现有数据进行自动排序,直到显式使用 OPTIMIZE
OPTIMIZE table_name [WHERE predicate] [ORDER BY columns] [ZORDER BY columns];

参数说明

  • table_name:要优化的表名。
  • WHERE predicate:可选,限制要优化的分区或数据行。
  • ORDER BY columns:可选,指定结果文件的排序方式。
  • ZORDER BY columns:可选,设置 Z-Ordering,以优化特定列的查询性能。

注意事项

  • 尽管 WRITE ORDERED BY 能提高后续查询性能,但可能增加写入延迟。合理选择排序列对性能有重要影响。

分区与排序结合

  • 可以将 WRITE ORDERED BY 与分区相结合进一步提高性能,确保分区内部有序写入。

任务内排序

  • 类似于 Spark 的 sort by,仅适用于 MERGE INTOUPDATEDELETE
ALTER TABLE prod.db.sample WRITE LOCALLY ORDERED BY category, id;

插入和覆盖

  • 使用手动排序:
INSERT OVERWRITE TABLE target_table SELECT * FROM source_table SORT BY date;

建立集群优先选择

  • 推荐使用 CLUSTER BY(cluster by = distribute by + sort by)。解决数据倾斜:
INSERT OVERWRITE TABLE target_table SELECT * FROM source_table CLUSTER BY date;

以上是关于 Apache Iceberg 数据操作的优化指南,包括行级更新、数据分布和排序写入策略。通过这些策略,可以显著提升数据处理性能和存储效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值