我在从OLTP环境到Redshift的ETLing可更新表中遇到性能问题。我们的基本工作流程是典型的OLTP-> S3-> Redshift数据流。假设我想ETL像这样的表
create table source_data (
id int primary key,
status varchar,
value decimal(10,4),
dateLastTouched datetime,
dateCreated datetime,
index datelasttouched_index (dateLastTouched));
到Redshift中的类似表格。在准备ETL时,我创建了排序键dateLastTouched
和dist键id
。在上一个作业的最大dateLastTouched ETLd之后,我们ETL具有dateLastTouched的任何记录。
对于没有更新旧记录的表(例如去年的记录改变其状态),此设置非常有效,但是当您添加该功能时,我无法有效地看到ETL。我们目前的做法是:
鉴于我们使用dateLastTouched设置排序键,步骤3非常慢。通常需要1-2分钟,并且随着时间的推移非常明显地需要更长时间。我们无法将排序键更改为主键,因为我们需要dateLastTouched来报告在表上频繁运行的查询。 我们考虑过的一些想法:
从S3到Redshift的高效upsert是否有更好的范例?或者我只需要吃掉ETL /物化视图成本?
答案 0 :(得分:3)
另一种选择是拥有2个版本的表,一个用于用于ETL的dateLastTouched
,另一个用于用于报告的order by
。当ETL过程在第一个上完成时,您只需重新创建第二个(不使用truncate t2
,而只使用insert into t2 select * from t1
,vacuum reindex t2
和CREATE FUNCTION dbo.tfn_Tally
/* ============================================================================
07/20/2017 JL, Created. Capable of creating a sequense of rows
ranging from -10,000,000,000,000,000 to 10,000,000,000,000,000
============================================================================ */
(
@NumOfRows BIGINT,
@StartWith BIGINT
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)), -- 10 rows
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b), -- 100 rows
cte_n3 (n) AS (SELECT 1 FROM cte_n2 a CROSS JOIN cte_n2 b), -- 10,000 rows
cte_n4 (n) AS (SELECT 1 FROM cte_n3 a CROSS JOIN cte_n3 b), -- 100,000,000 rows
cte_Tally (n) AS (
SELECT TOP (@NumOfRows)
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) + @StartWith
FROM
cte_n4 a CROSS JOIN cte_n4 b -- 10,000,000,000,000,000 rows
)
SELECT
t.n
FROM
cte_Tally t;
GO
)
此外,根据表的大小和群集的配置,实际上可以更快地重新加载表的整个主体而不需要处理upsert