我的sql合并语句运行时间过长

s71maibg  于 2021-06-26  发布在  Hive
关注(0)|答案(1)|浏览(603)

我有一个配置单元合并语句:

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说:
sql标准要求,如果on子句使源中的多行与目标中的行匹配,则会引发错误。此检查的计算开销很大,可能会显著影响merge语句的整体运行时。hive.merge.cardinality.check=false可用于禁用检查,风险自负。如果检查被禁用,但语句具有这种交叉连接效应,则可能导致数据损坏。
我确实禁用了基数检查,因为虽然on语句在source中可能会给出2行,但是由于match子句后面的r=1,这些行被限制为1。
总的来说,我喜欢这个合并声明,但它只是太慢,任何帮助将不胜感激。
注意,目标表是分区的。源表不是,因为它是一个外部表,每次运行都必须完全合并,因此完全扫描(在后台,已合并的数据文件将被删除,新文件将在下次运行之前添加)。不确定分区在这种情况下是否有用
我所做的:
播放hdfs/Hive/Yarn配置
尝试使用临时表(2个步骤)而不是单个合并,运行时间跳到2小时以上。

4jb9z9bj

4jb9z9bj1#

选项1:移动过滤器 where src.r = 1 内部 src 子查询并检查合并性能。这将减少合并前的源行数。
其他两个选项不需要acid模式。执行完全目标重写。
选项2:使用union all+行号重写(这应该是最快的一个):

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

如果源中包含大量重复项,则可以在联合之前对src子查询应用额外的行号筛选。
还有一种方法是使用fulljoin:https网址:stackoverflow.com/a/37744071/2700344

相关问题