[Hive][COUNT] 使用count后出現null問題排查


[Hive][COUNT] 使用count后出現null問題排查

問題概述

使用hive進行用戶頻次類數據分組提取時,最終的結果出現了全部為null的記錄,同時也有全為0的記錄,分析原因

v1HQL邏輯

with sup_tab as(

取出用戶所用行為記錄

)

select 用戶id, count( 條件1 ) as cnt_1, count( 條件2 ) as cnt_2 ,...

from sup_tab

where 時間窗口限制

group by 用戶標識

v1存在問題

由於HQL的select后的字段只能是統計字段,以及分組字段,即只能出現count,sum,avg等聚合函數和group by 字段之后的分組字段,所以,若想要使得用戶id(非用戶標識)出現在最終的表中,所以我采用了以下邏輯

v2HQL邏輯

with sup_tab as(

取出用戶所用行為記錄

)

select 用戶id, count( 條件1 ) as cnt_1, count( 條件2 ) as cnt_2 ,...

from (

​ 用戶基本信息

​ from sup_tab

) id

left join

(

​ 統計量

​ from sup_tab

​ where 時間窗口限制

​ group by 用戶標識

) cnt

on id.用戶標識 = cnt.用戶標識

為什么不使用用戶id進行分組統計

因為用戶id字段存在空值和非法值

問題分析

首先明確三點

  • A left join B B中若無A的條目,則全部填充為NULL
  • COUNT(NULL) = 0
  • select COUNT from where 是對滿足了where后的數據進行操作

問題出在統計頻次時,使用了時間窗口進行過濾,這導致一些用戶的行為全部被過濾掉,所以在最終統計過程中沒有這個人,在left join過程中出現了NULL填充現象

解決方法

方案一:使用 inner join 代替 left join

好處:直接去除沒有數據的用戶,不會出現全NULL的用戶了

壞處:需要shuffle操作,這導致HQL執行速度down

方案二:不使用id表,直接從cnt表中獲得用戶id

v1方法: 將用戶id加在group by 后

是否有潛在風險?

首先明確以下兩點邏輯

  • HQL會根據group by后面的字段進行分組統計 如果有ABC三個字段,如果A中有a個不重復字段,B中有b個不重復字段,C中有c個不重復字段,在不考慮where過濾的情況下,那么最終會出現abc個數據記錄
  • 想輸出用戶id時,一個用戶標識字段中對應一個用戶id(可能是空值或非法值,但同一個用戶標識字段內,對應的用戶id都相同,是空值時均為空值,是非法值時均為非法值)

所以使用v1方法,理論上是存在風險的,但是實際在操作過程中,是可以規避風險的

好處:回避join導致的shuffle

壞處,group by 后字段數量增加,效率可能降低? (這一點是我有所顧慮的,沒有去實踐)

v2方法,使用collect_set(字段)[0]方法

collect_set(字段)可以將數據記錄,然后返回一個去重后的列表,常用做列轉行數據,如果不想對數據進行去重,那么使用collect_list(字段)即可,只需要取這個去重列表的第0個數據就可以達到獲得用戶ID的目的,根據v1方法的分析,在使用collect_set進行突破group by限制時,其中只會有一個數據,如果有一個以上時,說明一個用戶識別字段對應多個用戶ID,需要進行排查。

寫在最后

由於公司數據需要保密,所以基本上只能描述問題和思路,具體問題不能直觀貼出來,SQL的相關邏輯還是要多進行測試,但直接拿大數據表來測試邏輯又不合適,我並沒有學習過MySQL這種SQL類編程,所以,找了一個在線練習的網站,希望有相同問題的朋友可以在一些在線網站測試一些簡單邏輯,就不用裝SQL到個人PC上了。

SQL邏輯練習

https://sqlzoo.net/wiki/Using_Null/zh




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM