最近業(yè)務場景需要將一張大表通過name名字關(guān)聯(lián)多個小表去獲取他們的id,大表數(shù)據(jù)9000w,小表數(shù)據(jù)最大180w,最小30w,我以主表leftjoin的時候發(fā)現(xiàn)了數(shù)據(jù)丟失問題
代碼如下?
select eid, concat_ws(',', hat_name1, hat_name2, hat_name3, hat_name4, hat_name5, hat_name6) as hat_name
from (select t1.eid,
if(t1.name = t2.name, hat_name1, null) as hat_name1,
if(t1.name = t3.name, hat_name2, null) as hat_name2,
if(t1.name = t4.name, t4.hat_name, null) as hat_name3,
if(t1.name = t5.name, hat_name4, null) as hat_name4,
if(t1.name = t6.name, t6.hat_name, null) as hat_name5,
if(t1.eid = t7.eid, t7.hat_name, null) as hat_name6
from temp_a t1
left join temp_a t2 on t1.format_name = t2.name
left join temp_b t3 on t1.credit_no = t3.code
left join temp_c t4 on t1.format_name = t4.name
left join temp_d t5 on t1.format_name = t5.name
left join temp_e = t6.eid
left join temp_f t7 on t1.eid = t7.eid) t;
結(jié)果顯示數(shù)據(jù)我t7的數(shù)據(jù)由180w剩下9w,發(fā)生了嚴重的數(shù)據(jù)丟失,在別的表也有不同程度的丟失問題.
最后發(fā)現(xiàn)這個問題主要是hive3版本底層mr的缺陷,是由于 HIVE 2 與 HIVE 3 在 JOIN 操作時使用了不同的 Hash 算法,導致同樣的值在關(guān)聯(lián)時被不同的 Hash 算法映射成了不同的值,而這些不同的 Hash 值在進行關(guān)聯(lián)時無法被相互匹配。最終導致本來該被關(guān)聯(lián)在一起的數(shù)據(jù)由于 Hash 值得不同未能被關(guān)聯(lián)在一起。而決定到底應用哪套 Hash 值算法則是根據(jù) bucketing_version 的值來進行評判的。
特別地,在進行多表關(guān)聯(lián)時,即使相同 bucketing_version 的 Hive 表,由于其關(guān)聯(lián)的中間過程所產(chǎn)生的中間表,在源代碼中 bucketing_version 值會被置為 -1,因此該中間表再與第三張乃至更多的表關(guān)聯(lián)時會直接導致 Hash 算法的混亂計算。
因此,為了保障關(guān)聯(lián)的數(shù)據(jù)準確性,必須要確保 bucketing_version 在進行多表關(guān)聯(lián)或者多版本表關(guān)聯(lián)時的穩(wěn)定。即,保障 bucketing_version 的穩(wěn)定性就是保證 Hive 3 數(shù)據(jù)關(guān)聯(lián)時的準確性。
此外,HIVE 社區(qū)已經(jīng)針對 bucketing_version 不穩(wěn)定的問題進行了集中的問題匯總和修改建議指導。可以通過查看 JIRA: HIVE-21304 了解系統(tǒng)性的 bucketing_version 穩(wěn)定性提高方法,此處不做過多贅述。此處引出之前看到文章:
https://blog.csdn.net/weixin_38070561/article/details/126895259
此外,除了上面通過源碼的修改來解決之類問題,我也從sql上考慮解決該問題的可行性,如果多表leftjoin可能造成數(shù)據(jù)丟失,那我們是否可以盡量的少去關(guān)聯(lián)它呢?
因為我的業(yè)務是為了獲取主表的id,所以我采用了unionall的方法,將各個小表以臨時表的方式unionall一起,然后跟主表left去獲取他的id,這是我就從6表關(guān)聯(lián)變成了1表關(guān)聯(lián),代碼如下:
?文章來源:http://www.zghlxwxcb.cn/news/detail-557569.html
select eid, name, hat_name, hat_id
from (select eid, name, hat_name, hat_id
from temp_a
union all
select eid, name, hat_name, hat_id
from temp_b
union all
select eid, name, hat_name, hat_id
from temp_c
union all
select '' as eid, name, hat_name, hat_id
from temp_d
union all
select eid, name, hat_name, hat_id
from temp_e
union all
select '' as eid, name, hat_name, hat_id
from temp_f
) t1
group by eid, name, hat_name, hat_id
因為考慮數(shù)據(jù)安全,代碼僅發(fā)表部分,大概就是這個意思,上面的數(shù)據(jù)插入臨時表后與大表關(guān)聯(lián)也可以有效防止數(shù)據(jù)丟失,當然這個辦法只能說是治標不治本的辦法,因為業(yè)務比較急才走的捷徑,歸根到底還是得從根源上解決問題文章來源地址http://www.zghlxwxcb.cn/news/detail-557569.html
到了這里,關(guān)于關(guān)于hive3多表leftjoin導致數(shù)據(jù)丟失問題及解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!