在vertica中交叉两个大小为500ml的行
Posted
技术标签:
【中文标题】在vertica中交叉两个大小为500ml的行【英文标题】:INTERSECT two table of size 500ml rows in vertica 【发布时间】:2020-01-19 04:29:00 【问题描述】:我对 vertica db 非常陌生,因此正在寻找不同的有效方法来比较 vertica 中平均大小为 500ml-800ml 的两个表。我有一个从 vertica 视图获取数据并将数据转储到 SQL Server 以供稍后合并到 sql server 中的最终表的过程。对于几张大桌子来说,它每天会倾倒大约 3bl 行。我不想转储所有数据,而是每天拍摄快照,并将其与前几天仅在 vertica 端的快照进行比较,然后仅将更改的行推送到 SQL SEREVER。
假设以前的快照存储在 tableA 中,今天的快照存储在 tableB 中。两个表上的 PK 都是名为 OrderId 的列。
我能想到的最简单的方法是
Select * from tableB
Where OrderId NOT IN (
SELECT * from tableA
INTERSECT
SELECT * from tbleB
)
所以我的问题是:
-
vertica 中是否有任何其他/更好的选项来仅获取两个表之间更改的行?或者我应该
甚至考虑在 vertica 端进行此比较?
进行这样的比较需要多少时间?
我应该考虑什么来提高此类查询的性能?
【问题讨论】:
我认为您的代码不会在 Vertica 上运行,除非表格只有一列。 【参考方案1】:如果您的列没有 NULL
值,那么大量的 LEFT JOIN
似乎可以满足您的需求:
select b.*
from tableB b left join
tableA a
on b.OrderId = a.OrderId and
b.col1 = a.col1 and
. . . -- for all the columns you care about
但是,我想你想要except
:
select b.*
from tableB b
except
select a.*
from tableA a;
我想这会有合理的表现。
【讨论】:
谢谢。是的,我想 EXCEPT 也是选项,因为我没有“行存在于 tableA 但不存在于 tableB”的用例 因为我关心所有列 LEFT JOIN 对我来说不是一个好选择。除了/相交似乎更清洁的方式。 关于“合理的性能”,您是否真的在大容量表上使用过 vertica?我正在寻找这样的粗略估计,这样应该需要不到 30 秒或 1 分钟等。如果性能不低于几秒钟,我想知道是否需要与 vertica dba 讨论任何 vertica 集群级别的配置。所以我希望你有什么指点让我看看。 @anupShah 。 . .如果这与您的配置有关,您应该与您的 dba 交谈。 您好,只是为了让您知道可能有更多的选择和方法,但今天我尝试比较两个表,每个表 250 毫升行,20 毫升行有差异,使用 EXCEPT 方法在 2 分钟内完成。所以这对我的工作流程来说是可以接受的,所以我标记接受你的答案。【参考方案2】:你有两个表的主键吗?
那么对于完整的变更数据捕获,我的技术是:
SELECT
'I' AS to_do
, newrows.*
FROM tb_today newrows
LEFT
JOIN tb_yesterday oldrows USING(id)
WHERE oldrows.id IS NULL
UNION ALL
SELECT
'U' AS to_do
, newrows.*
FROM tb_today newrows
JOIN tb_yesterday oldrows
WHERE oldrows.fname <> newrows.fname
OR oldrows.lnamd <> newrows.lname
OR oldrows.bdate <> newrwos.bdate
OR oldrows.sal <> newrows.sal
[...]
OR oldrows.lastcol <> newrows.lastcol
UNION ALL
SELECT
'D' AS to_do
, oldrows.*
FROM tb_yesterday oldrows
LEFT
JOIN tb_today oldrows USING(id)
WHERE newrows.id IS NULL
;
如果您不想满足 DELETE ('D') 的需求,只需省略 UNION SELECT 的最后一站
祝你好运
【讨论】:
是的。感谢您的回复。但由于我有 70 多列,除非这种技术在性能或其他方面有一些主要优势,否则 INTERSECT/EXCEPT 不是更容易读写,因为我不必编写所有列比较? EXCEPT 运算符与 UNION 运算符一样易于编码,是的。但是通过主键连接(默认情况下,这会导致两个表都按主键排序和分段,因此具有最佳访问路径)比所有 70 个哈希表的资源密集度要低几个数量级+ 表的列,因为它对于 UNION(暗示 DISTINCT)或 EXCEPT/INTERSECT 是必需的。 70 多次比较发生在正在处理的一行中,而且成本要低得多。另外,您可以从columns
系统表中生成语句。【参考方案3】:
你也可以很好地使用连接:
SELECT b.*
FROM tableB AS b
LEFT JOIN tableA AS a ON a.id = b.id
WHERE a.id IS NULL
所以上面的查询只返回从 TableB 到 TableA 的差异,即两个表中都存在的数据将被跳过...
【讨论】:
Intersect 正在比较所有列。不仅是PK列。当您执行 LFET JOIN 时,它只检查该 PK 值是否存在。如果存在,它不会检查所有列的值是否相同。所以它和INTERSECT的逻辑不一样。以上是关于在vertica中交叉两个大小为500ml的行的主要内容,如果未能解决你的问题,请参考以下文章