【发布时间】:2021-11-22 05:55:43
【问题描述】:
我在生产中有大约 50 个查询。每个查询都返回两列 - 用户 ID 和一些计算列
要求是所有这些查询都应该通过 userid 将计算列加入结果表中。
例如:-
查询 1st 返回以下列数据:-
-------------
userid | c1 |
-------------
类似查询第二次:-
-------------
userid | c2 |
-------------
第 50 次查询:-
-------------
userid | c50 |
-------------
现在每个查询的计算列输出应该附加到一个结果主表中,例如:-
--------------------------------------------------
userid | c1 | c2 | c3 |..............| c49 | c50 |
--------------------------------------------------
现在最天真的方法是将每个查询的输出写入单独的临时表,并将用户 ID 上的每个表连接到单个结果表。这个问题我不想通过创建临时表来污染命名空间到这种程度,因为这是红移并且表真的很大,提交每个临时表本身将在存储方面产生重大成本。
我认为下一个解决方案是使用“with”CTE:-
insert into Resultant
with rel1 as (select userid, c1 from t1 ),
rel2 as (select userid,c2 from t2 ),
.
.
rel50 as (select userid, c50 from t50)
select * from rel1 inner join rel2 on rel1.userid = rel2.userid
inner join rel3 on rel2.userid = rel3.userid
...
...
inner join rel50 on rel49.userid = rel50.userid
我不知道这个解决方案的优化程度如何。 Redshift docs 提到:-
在可能的情况下,多次引用的 WITH 子句子查询被优化为公共子表达式;也就是说,有可能对 WITH 子查询进行一次评估并重用其结果。
另一种方法是使用 50 个更新连接:-
update resultant set resultant.col1 = (select Q.col1 from ("inner query that generates userid and col1) Q inner join resultant on resultant.userid = Q.userid );
update resultant set resultant.col2 = (select Q.col2 from ("inner query that generates userid and col1) Q inner join resultant on resultant.userid = Q.userid );
update resultant set resultant.col50 = (select Q.col50 from ("inner query that generates userid and col1) Q inner join resultant on resultant.userid = Q.userid );
这种方法会产生更多成本吗?由于 Redshift 是基于列的,我希望它不必更新整行。
有没有比这两种方法更优化的存储过程中执行此操作的方法?理想情况下,如果绝对没有必要,我想避免存储过程。 每个查询返回大约 50GB 的结果集。
【问题讨论】:
-
更新一列时,会更新整行。每列中的值都有一个行号,每列的行号必须相同。原始行设置了 delete_xid,并且为每一列创建了一个全新的行。
标签: sql stored-procedures amazon-redshift common-table-expression