Hive效率低下的嵌套连接

时间:2015-06-12 16:38:21

标签: hive

我有两个可以通过公共密钥(即交易ID)加入的大型Hive表(数十亿条记录)。 table_a包含所有交易ID,table_b在某些时候有交易。

enter image description here

理论上,两个表中都不应有重复的交易ID。在实践中,有一些重复,虽然它们的数量相对较少,但是很多:很多连接都有可能导致问题。我根据这些数据构建模型,作为第一步,可能更容易忽略所有具有重复交易ID的记录。

我写了一个丑陋的Hive查询,虽然它在逻辑上做了它需要做的事情,但它的效率非常低:

SELECT
   table_a.someCol,
   table_b.anotherCol,
   [etc...]
FROM
    (SELECT
       table_a.*
     FROM table_a
     INNER JOIN
       (SELECT
          transaction_id
        FROM table_a
        GROUP BY transaction_id
        HAVING COUNT(*) = 1) unique_transaction_ids
    ON table_a.transaction_id = unique_transaction_ids.transaction_id) table_a_unique_transaction_ids_only
LEFT OUTER JOIN
    (SELECT
       table_b.*
     FROM table_b
     INNER JOIN
      (SELECT
         transaction_id
       FROM table_b
       GROUP BY transaction_id
       HAVING COUNT(*) = 1) unique_transaction_ids
    ON table_b.transaction_id = unique_transaction_ids.transaction_id) table_b_unique_transaction_ids_only
ON table_a_unique_transaction_ids_only.transaction_id = table_b_unique_transaction_ids_only.transaction_id;

工作原理:

首先,对于两个表,创建一个只出现一次的交易ID列表:

SELECT
    transaction_id
FROM table_?
GROUP BY transaction_id
HAVING COUNT(*) = 1

然后通过将唯一事务子查询内部连接到原始表来过滤表。

最后,左外连接已过滤的子查询。

是否有更有效的方式来编写此内容(例如使用ROW_NUMBER() OVER ...等分析函数)?

1 个答案:

答案 0 :(得分:1)

如果您想要table_atable_bLEFT OUTER JOIN似乎是不可避免的。可以避免两个自连接。由于您只需要transaction_id只发生过一次,因此您可以在其余列上使用MAX()MIN()而不会丢失信息(即使它们不是数字列)。像

这样的东西
select transaction_id
  , max(col1) col1
  , max(col2) col2
        .
        .
        .
  , max(coln) coln
from table_a
group by transaction_id
having count(transaction_id) = 1

这是一种通过"拉出列的方式。到下一个"级别"无需group by他们。如果你有很多专栏,那么编写它可能会很乏味,但通常值得避免两个自连接。