在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的行的主要内容,如果未能解决你的问题,请参考以下文章

使用vertica数据库系统获取java jpa的行级锁

如何在没有交叉产品的情况下从 BigQuery 中的两列中取消嵌套两个列表,作为单独的行

UIScrollView 缩小具有 -ve 原点的视图

pyspark - 如何交叉验证几种 ML 算法

vertica数据库客户端调整字体大小

PHP有限内存处理大文件(从两个文件提取相同行)