2015-06-12 61 views
1

我有两个可以通过公用密钥(即事务ID)连接的大型Hive表(数十亿条记录)。 table_a包含所有交易ID,并且table_b在一段时间内有交易。Hive低效嵌套连接

enter image description here

从理论上讲,应该是没有重复的事务ID,在任何一个表。在实践中,有一些重复项,虽然数量相对较少,但很多重复项有潜在的问题。我正在建立一个基于这些数据的模型,作为第一遍,可能更容易忽略所有具有重复事务ID的记录。

我写了一个丑陋的蜂巢查询,虽然它在逻辑上做的事情需要做,它的效率极其低下:

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 ...)?

+0

你在'table_a'&'table_b'中有多少列? – gobrewers14

+0

这两个表格都包含37列,主要是字符串。 –

回答

1

如果你想table_atable_b在一起,LEFT 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他们的方式。如果你有很多列,但通常是值得的,以避免两个自我连接,那么编写它可能会很乏味。