2015-06-12 60 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他們的方式。如果你有很多列,但通常是值得的,以避免兩個自我連接,那麼編寫它可能會很乏味。