【问题标题】:Hive comparison with aggregate result from subqueryHive 与子查询的聚合结果比较
【发布时间】:2017-06-21 11:16:00
【问题描述】:

我有一个像这样的表(例如,称为 Source):

-------------
|Name|ID|...|
-------------
|A   |1 |...|
|A   |2 |...|
|A   |3 |...|
|B   |1 |...|
|B   |2 |...|
|C   |1 |...|
-------------

所以每个 Name 可能有多个条目,每个条目都有一个递增的 ID(它又由 Name 分区,因为您可能已经知道了现在)。

现在,我有另一个表(称为 Dest),我从 Source 表加载,例如每日批次。但是,我只想从 Source 加载增量,所以如果我的 Dest 表是这样的:

-------------
|Name|ID|...|
-------------
|A   |1 |...|
|A   |2 |...|
|B   |1 |...|
-------------

我只想将 Source 的差异复制到 Dest ,即:

-------------
|Name|ID|...|
-------------
|A   |3 |...|
|B   |2 |...|
|C   |1 |...|
-------------

由于其他原因,我不能为此使用时间戳或减号,因此找到差异的唯一方法是获取每个 NameMAX(ID) > 并仅检索每个 Name 的条目 > MAX(ID)

最快的实现是通过一个子查询为每个Name准备所有MAX(ID),并用它来消除较小的ID强>s:

SELECT s.* FROM Source s 
LEFT JOIN (
 SELECT d.NAME, MAX(d.ID) AS MAX_ID
 FROM Dest d
 GROUP BY d.NAME) n
ON s.NAME = n.NAME
WHERE s.ID > COALESCE(n.MAX_ID,0)

但是,由于表中有很多条目,我相信这不会很好执行,除非 Hive 自动对其进行了足够的优化,我不确定。

我希望做的是这样的:

SELECT s.* FROM Source s 
WHERE s.ID > (SELECT COALESCE(MAX(d.ID),0)
              FROM Dest d
              WHERE d.NAME = s.NAME)

这样,我将避免为所有条目计算 MAX(ID),而只会为当前 Name 计算它。但这显然在 Hive 中是不可能的。

所以我的问题是,在 Hive 中实现这种增量检测的最佳和最有效的方法是什么?

【问题讨论】:

    标签: sql hadoop hive delta


    【解决方案1】:

    为什么不直接使用left joinwhere

    SELECT s.*
    FROM Source s LEFT JOIN
         Dest d
         ON s.NAME = d.NAME AND s.ID = d.ID
    WHERE d.NAME IS NULL;
    

    如果您确实需要使用来自 Dest 的最大 id 来执行此操作,那么您使用 GROUP BY 的方法在 Hive 中应该没问题。

    【讨论】:

    • 原因是因为实际上Source表是一种历史档案,特别是每次在名称中添加一些ID时,也会添加以前的ID。例如。昨天添加了名称 A 的条目 1, 2,今天添加了名称 A 的条目 1,2,3添加,所以再次添加 1,2,然后添加 3。这使得很难使用您的方法或时间戳。我的GROUP BY 方法在数百万个条目中仍然表现良好,还是有更好的方法,比如第二种方法的替代方法?
    • @Johnny16 。 . .正如您描述的问题,left join 应该仍然可以工作(即使有重复)。但是,它确实使group by 更可口。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 2018-12-11
    • 1970-01-01
    相关资源
    最近更新 更多