我有这个Hive 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
)
;
哪个运行很长时间(磁盘上7GB的avro压缩数据为30分钟)。 我想知道是否有任何SQL方法可以改进它。
ROW_NUMBER()用于对源表进行重复数据删除,因此在MATCH子句中我们只选择最早的行。
我不确定的一件事是hive says:
如果ON子句是这样的话,SQL标准要求引发错误 源中超过1行与目标中的行匹配。这个检查是 计算成本高,可能影响a的整体运行时间 MERGE声明显着。 hive.merge.cardinality.check = false可能 用于禁用检查的风险由您自行承担。如果检查是 禁用,但声明有这样的交叉连接效果,它可能会导致 数据损坏。
我确实禁用了基数检查,因为虽然ON语句可能在源代码中提供2行,但由于MATCH子句中的r = 1,这些行仅限于1。
总的来说,我喜欢这个MERGE声明,但它太慢了,任何帮助都会受到赞赏。
请注意,目标表已分区。源表不是因为它是一个外部表,每次运行必须完全合并,所以完全扫描(在后台已经合并的数据文件被删除,新文件在下次运行之前添加)。在这种情况下,不确定分区是否有用
我做了什么:
答案 0 :(得分:1)
选项1:移动where src.r = 1
子查询中的过滤器src
,并检查合并性能。这将减少合并前的源行数。
其他两个选项不需要ACID模式。完全目标重写。
选项2:使用UNION ALL + row_number重写(这应该是最快的):
insert overwrite table destination
select
company
, contact_id as id
, ct.cid as cid
, email
, timestamp_utc
, -- add more fields
from
(
select --dedupe, select last updated rows using row_number
s.*
, ROW_NUMBER() OVER (PARTITION BY company, ct.id , contact_id ORDER BY timestamp_utc DESC) as rn
from
(
select --union all source and target
company
, contact_id as id
, ct.cid as cid
, email
, timestamp_utc
, -- add more fields
from source LATERAL VIEW explode(campaign_id) ct AS cid
UNION ALL
select
company
, contact_id as id
, ct.cid as cid
, email
, timestamp_utc
,-- add more fields
from destination
)s --union all
where rn=1 --filter duplicates
)s-- filtered dups
如果source包含大量重复项,则可以在union之前对src子查询应用其他row_number过滤。
使用完全加入的另一种方法: https://stackoverflow.com/a/37744071/2700344