如何在 Redshift 中批量更新设置值?

Posted

技术标签:

【中文标题】如何在 Redshift 中批量更新设置值?【英文标题】:how to do bulk update set values in Redshift? 【发布时间】:2021-11-08 14:55:11 【问题描述】:

我已经看到其他数据库的类似问题,但不确定它们是否适用于 Redshift。

我有一个这样的更新语句,需要应用到很多列:

update t1 set col1 = '' where col1 is null;

现在我正在为 30 列执行此操作。有没有办法动态或从列表中做?

我可以在存储过程或函数中做吗?

【问题讨论】:

【参考方案1】:

这里有两个问题。您想查找文本列的列表,并且不想运行 N 次更新,因为这可能会产生大量无效行、空间损失和需要清理。

第二个问题是因为 Redshift 是一个列式数据库,并不真正更新行,它使现有行无效并添加新行。如果您正在清理大型表中许多行中的 NULL,这可能会导致许多需要清理的无效行。如果您正在运行多个 UPDATE,每列一个,这会变得更糟,因为每个 UPDATE 可能会为每个 UPDATE 生成同一行的新版本(留下无效行)。在这种情况下,您最好只运行一次更新所有列和所有行的 UPDATE。 (代码如下)

但是,如果您只更新表中的几行(低 NULL 计数),那么只更新那些具有 NULL 的行会更好。在这种情况下,您确实需要添加一个 WHERE 子句来防止制作没有 NULL 的行的精确副本。这很简单:

设置测试用例:

create table fred (
col_a varchar(8),
col_b varchar(8),
col_c varchar(8));

insert into fred values 
('a', NULL, NULL),
(NULL, 'b', NULL),
(NULL, NULL, 'c');

现在,如果我们要更新所有行的所有列,我们可以运行:

update fred set 
    col_a = nvl(col_a,''),
    col_b = nvl(col_b,''),
    col_c = nvl(col_c,'') 
where col_a is null or col_b is null or col_c is null;

回到问题的第一部分 - 如何生成列列表并动态进行此查询?我喜欢为 Redshift 提供外部 DDL 定义文件,因为这样可以更轻松地链接 Redshift 数据和其他 AWS 数据。一个源文件,可以从中生成 Redshift DDL 和 Athena DDL 以及任何其他 DDL。但这不太可能是你的情况。

可以在 Redshift 中的许多系统表中访问表 DDL。在这种情况下,最容易访问的可能是 information_schema.columns。喜欢:

select column_name, data_type from information_schema.columns where table_schema = 'public' and table_name = 'fred'; 

这将为您提供任何表中列的名称和数据类型。由于您将值设置为 '' 此过程仅适用于文本数据类型,因此您可能需要为要更改的数据类型添加额外的 WHERE 子句。

现在有了列列表,您需要创建上面的查询。这只是遍历列并生成上面查询的 SELECT 部分和 WHERE 部分的字符串部分。这有很多方法可以做到这一点。我个人喜欢 jinja2 将列表应用于模板以生成配置文本(如查询)。我还喜欢让 Redshift 专注于执行繁重的分析查询,而不是让它成为一个操作环境,因此我远离存储过程。但是,如果您愿意,没有理由不能将此过程编码为存储过程。如果我需要定期运行此数据清理过程,我会将其编码为我的 ETL(ETL 工具发出已编译查询)或 Lambda 函数的一部分。但这只是我。

【讨论】:

非常有帮助,谢谢

以上是关于如何在 Redshift 中批量更新设置值?的主要内容,如果未能解决你的问题,请参考以下文章

将日期时间列值批量转换和更新为 UNIX 时间戳?

如何在高效查询中快速批量更新值?

为啥批量插入/更新更快?批量更新如何工作?

批量插入的 Redshift 查询队列使用情况

我可以在更新gitattributes后使用Git批量更改行尾吗?

微批量加载到 Redshift - 一些实际问题