我有这个蜂巢MERGE语句运行: 我的SQL MERGE语句太久
MERGE INTO destination dst
USING (
SELECT
-- DISTINCT fields
company
, contact_id as id
, ct.cid as cid
-- other fields
, email
, timestamp_utc
-- there are actually about 6 more
-- deduplication
, ROW_NUMBER() OVER (
PARTITION BY company
, ct.id
, contact_id
ORDER BY timestamp_utc DESC
) as r
FROM
source
LATERAL VIEW explode(campaign_id) ct AS cid
) src
ON
dst.company = src.company
AND dst.campaign_id = src.cid
AND dst.id = src.id
-- On match: keep latest loaded
WHEN MATCHED
AND dst.updated_on_utc < src.timestamp_utc
AND src.r = 1
THEN UPDATE SET
email = src.email
, updated_on_utc = src.timestamp_utc
WHEN NOT MATCHED AND src.r = 1 THEN INSERT VALUES (
src.id
, src.email
, src.timestamp_utc
, src.license_name
, src.cid
)
;
这对于一个很长的时间(30分钟Avro的压缩数据的7GB在磁盘上)上运行。 我不知道是否有任何SQL方法来改善它。
ROW_NUMBER()在这里对源表进行重复数据删除,因此在MATCH子句中我们只选择最早的行。
有一两件事我不知道的是,hive says:
SQL标准要求,如果ON子句是这样 超过1行中源目标相匹配的行抛出一个错误。此检查为 计算量很大,并且可能会显着影响MERGE语句的整体运行时间。 hive.merge.cardinality.check = false可能使用 禁用检查,风险自负。如果检查是 禁用,但声明具有这种交叉连接效果,则可能导致 数据损坏。
我确实禁用了基数检查,因为虽然ON语句可能在源中提供2行,但由于MATCH子句后面的r = 1,所以这些行仅限于1。
总的来说,我喜欢这个MERGE语句,但它太慢了,任何帮助,将不胜感激。
请注意,目标表是分区的。源表不是因为它是每个运行必须完全合并的外部表,所以完全扫描(在后台已经合并的数据文件被删除并且在下次运行之前添加新文件)。不知道分区会在这种情况下
我所做的帮助:
- 与HDFS /蜂巢/纱构造发挥
- 尝试用临时表(2级),而不是一个单一的MERGE,运行时间跳到了2个多小时。
谢谢,我运行性能测试与你不同的选择。我想知道插入覆盖 - 如果目标表(分区)有数百万行会发生什么?我觉得合并(例如)100k行到100M行要比插入100M行更快? – Guillaume
@Guillaume请分享你的结果。我在Hive 1.2上使用第二个选项。 – leftjoin
选项的问题:〜25-30分钟,你的选项1(src.r = 1在子查询中):30-35分钟,你的选项2(无酸,插入覆盖):〜32分钟,临时表:2h +。你的源/目的表有多大? – Guillaume