Redshift 中的高效 ETL 更新插入

Efficient ETL Upsert in Redshift

我在从我们的 OLTP 环境到 Redshift 的 ETLing 可更新 table 方面遇到了性能问题。我们的基本工作流程是典型的OLTP->S3->Redshift数据流。假设我想像这样 table

create table source_data (
id int primary key,
status varchar,
value decimal(10,4),
dateLastTouched datetime,
dateCreated datetime,
index datelasttouched_index (dateLastTouched));

类似于 Redshift 中的 table。为了准备 ETL,我制作了排序键 dateLastTouched 和距离键 id。我们在上一个作业的最大 dateLastTouched ETLd 之后 ETL 任何带有 dateLastTouched 的记录。

此设置非常适用于没有更新旧记录的 tables(例如,去年的记录改变了它的状态),但是当你添加那个能力时,我不能无论如何要有效地看到ETL。我们目前的做法是:

  1. 使用 dateLastTouched 将所有新的或更新的记录发送到 S3。
  2. 将数据从 S3 复制到暂存区 table。
  3. 从目标 table 中删除任何与新数据具有相同主键的记录。
  4. 插入暂存中的所有记录table。

鉴于我们将 dateLastTouched 设置为排序键,第 3 步非常非常慢。通常需要 1-2 分钟,很明显随着时间的推移需要更长的时间。我们无法将排序键更改为主键,因为我们需要 dateLastTouched 来报告 运行 在 table 上相当频繁的查询。 我们考虑过的一些想法:

  1. id 和 dateLastTouched 的交错排序键。我们在另一个 table 上进行了尝试,但性能提升并不显着。真空重新索引时间也很糟糕。
  2. 不要删除,只需插入并让定期作业将 "latest record per id" 实现到另一个 table。这并不理想,因为它实际上使 table 占用的 space 翻了一番,而且更新并不频繁。

从 S3 到 Redshift 是否有更好的高效更新范例?还是我只需要吃ETL/materialized-view的费用?

另一种选择是使用 table 的 2 个版本,一个按 id 排序用于 ETL,另一个按 dateLastTouched 排序用于报告。当第一个 ETL 过程完成后,您只需重新创建第二个(不使用 order by,而仅使用 truncate t2insert into t2 select * from t1vacuum reindex t2

此外,根据集群的 table 大小和配置,重新加载 table 的整个主体实际上可能更快,而不考虑 upsert