【发布时间】:2017-10-05 14:01:55
【问题描述】:
我有这个 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 行与目标中的行匹配。这个检查是 计算成本高,可能会影响一个整体的运行时间 MERGE 语句显着。 hive.merge.cardinality.check=false 可能 用于禁用检查,风险自负。如果支票是 disabled,但是语句有这样的交叉连接效果,可能会导致 数据损坏。
我确实禁用了基数检查,因为尽管 ON 语句可能会在源代码中提供 2 行,但这些行仅限于 1,这要归功于 MATCH 子句后面的 r=1。
总的来说,我喜欢这个 MERGE 语句,但它太慢了,我们将不胜感激。
请注意,目标表已分区。源表不是因为它是每次运行都必须完全合并的外部表,所以完全扫描(在后台已经合并的数据文件被删除,并在下次运行之前添加新文件)。不确定在这种情况下分区会有所帮助
我做了什么:
- 玩转 hdfs/hive/yarn 配置
- 尝试使用临时表(2 步)而不是单个 MERGE,运行时间跃升至 2 多个小时。
【问题讨论】: