使用Redshift Copy命令进行合并

时间:2016-02-26 23:45:11

标签: amazon-web-services amazon-redshift amazon-kinesis-firehose

我有一个迭代输入并将数据吐出到AWS Firehose的进程,我已将其配置为上传到我创建的redshift表。一个问题是有时行可以重复,因为进程需要重新评估数据。 类似的东西:

Event_date, event_id, event_cost
2015-06-25, 123, 3
2015-06-25, 123, 4

http://docs.aws.amazon.com/redshift/latest/dg/t_updating-inserting-using-staging-tables-.html

在那里,我想用新值替换旧行,如下所示:

insert into event_table_staging  
select event_date,event_id, event_cost from <s3 location>;

delete from event_table  
using event_table_staging  
where event_table.event_id = event_table_staging.event_id;

insert into target 
select * from event_table_staging;

delete from event_table_staging  
select * from event_table_staging;

是否可以执行以下操作:

Redshift columns: event_date,event_id,cost
copy event_table from <s3> 
(update event_table 
select c_source.event_date,c_source.event_id,c_source.cost from <s3 source> as c_source join event_table on c_source.event_id = event_table.event_id) 
CSV


copy event_table from <s3> 
(insert into event_table 
select c_source.event_date,c_source.event_id,c_source.cost from event_table left outer join<s3 source> as c_source join on c_source.event_id = event_table.event_id where c_source.event_id is NULL) 
CSV

2 个答案:

答案 0 :(得分:3)

您无法直接从COPY进行合并。

但是,您的初始方法可以使用临时表包装在事务中,以便为最佳性能分级加载数据。

BEGIN
;
CREATE TEMP TABLE event_table_staging (
     event_date  TIMESTAMP  NULL
    ,event_id    BIGINT     NULL
    ,event_cost  INTEGER    NULL )
DISTSTYLE KEY
DISTKEY (event_id)
SORTKEY (event_id)
;
COPY event_table_staging  
FROM <s3 location>
COMPUDATE ON
;
UPDATE event_table  
SET    event_date = new.event_date
      ,event_cost = new.event_cost
FROM        event_table         AS trg
INNER JOIN  event_table_staging AS new
        ON  trg.event_id = new.event_id
WHERE COALESCE(trg.event_date,0) <> COALESCE(new.event_date,0)
  AND COALESCE(trg.event_cost,0) <> COALESCE(new.event_cost,0)
;
INSERT INTO event_table 
SELECT  event_date
       ,event_id  
       ,event_cost
FROM        event_table_staging AS new
LEFT JOIN   event_table         AS trg
       ON   trg.event_id = new.event_id
WHERE trg.event_id IS NULL
;
COMMIT
;

只要您使用交易并且更新总量相对低(单位数%),此方法实际上表现非常出色。唯一需要注意的是,您的目标需要定期VACUUM - 每月一次对我们来说足够了。

我们每小时对数百万行范围内的几个表进行此操作,即数百万行合并为数百万行的100。对合并表的用户查询仍然表现良好。

答案 1 :(得分:2)

Redshift经过优化,以经济高效的方式处理大量数据,您需要更改一些关于您从其他数据库获得的数据和数据库的想法。

主要概念是您不应该在Redshift中更新数据。您应该将Redshift中的数据视为&#34; Log&#34;。您可以将函数用作INSERT或UPDATE,但它们将限制您可以显着处理的数据量。

您可以通过多种方式处理重复项:

  • 您可以通过管理您正在处理的所有ID中的一些内存中查找表(例如,在ElastiCache上的Redis中)来防止首先写入重复项,如果您已经处理过了

  • 您可以在Redshift中保留重复内容并使用WINDOW函数处理这些记录,这些函数只会占用其中一条记录(例如LAST_VALUE)。

  • 您可以在Redshift中拥有原始事件,并在对DB的查询中进行聚合,而不是将其作为预处理进行。此模式还可以灵活地更改聚合数据的方式。通过这些聚合,Redshift可以非常快,并且几乎不需要预聚合。

如果您仍想要&#34;清洁&#34;和Redshift中的聚合数据一样,您可以UNLOAD使用正确的聚合或WINDOW函数进行某些SQL查询的数据,删除旧表并将数据复制回Redshift。