Ros*_* W. 5 etl amazon-redshift
我们正在 Redshift 集群上运行少量每小时脚本,这些脚本为数据消费者构建汇总表。组装临时表后,脚本然后运行一个事务,删除现有表并将其替换为临时表,如下所示:
BEGIN;
DROP TABLE IF EXISTS public.data_facts;
ALTER TABLE public.data_facts_stage RENAME TO data_facts;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
此操作的问题在于,长时间运行的分析查询会将 AccessShareLock 放在 上public.data_facts,以防止它被删除并破坏我们的 ETL 周期。我认为更好的解决方案是重命名现有表,如下所示:
ALTER TABLE public.data_facts RENAME TO data_facts_old;
ALTER TABLE public.data_facts_stage RENAME TO data_facts;
DROP TABLE public.data_facts_old;
Run Code Online (Sandbox Code Playgroud)
但是,这种方法的前提是 1)public.data_facts 存在,2)public.data_facts_old 不存在。
您知道是否有一种方法可以在 SQL 中安全地执行此操作,而不依赖于应用程序逻辑?(例如,像 ALTER TABLE IF EXISTS 这样的东西)。
您可以向目标表添加新load time timestamp encode runlength default getdate()列,并使 ETL 执行以下操作:
INSERT INTO public.data_facts
SELECT * FROM public.data_facts_staging;
DELETE FROM public.data_facts
WHERE load_time<(select max(load_time) from public.data_facts);
DROP TABLE public.data_facts_staging;
Run Code Online (Sandbox Code Playgroud)
注意:public.data_facts_staging应该具有与 完全相同的结构,除了ispublic.data_facts的最后一列,以便在插入时它将填充当前时间戳。public.data_factsload_time
唯一的含义是,在插入新行和删除旧行之间需要额外的磁盘空间,并且load_time必须始终是最后一列。vaccum而且每次这样做时你都必须餐桌。
这样做的另一个好处是,如果您的 ETL 失败并且临时表为空或没有临时表,您不会丢失数据。在使用 DDL 交换表的纯 SQL 场景中,当暂存表丢失时,您无法避免删除目标表。在建议的场景中,如果没有插入新行,则删除语句不会删除任何内容(没有行小于最大加载时间),因此最坏的情况是只有旧版本的数据。
ps 有一个命令不仅可以insert ... select ...将指针从暂存表更改为目标表(alter table ... append from ...),而且它需要与我猜测相同类型的锁alter table,所以我不建议这样做
| 归档时间: |
|
| 查看次数: |
3922 次 |
| 最近记录: |