場景(簡化)
現有文章表Article和評論表Comment;
一篇文章可以有多個評論;
文章表Article主要字段(articleId);
評論表Comment主要字段(commentId,articleId,content,createTime,lastChangeTime);
問題描述
發現很多文章下出現了評論內容一樣的評論,所以需要對文章的評論進行數據清洗,即同一文章下相同內容的點評只保留修改時間最晚的一條(請忽略是不是同一個用戶評論的問題);
解決步驟
- 接到需求當下的第一個想法是遍歷Article表,然後通過UDF調用線上服務,線上服務再拿articleId去處理評論重複的問題,雖然這個方法簡單,但是隻適合小數據量,所以得繼續觀察;
- 然後查一下設計清洗的數據量有多少(對於有數據倉庫的請不要在生產庫查詢,防止數據量太大影響線上功能),查詢的結果大概是兩千萬左右,數據量太大,起初的想法不合理,只能換其它的方法;
- 詢問了一下同事看有沒有什麼好的解決方案,同事說可以用SQL將需要清洗的數據篩選出來,由於我之前沒有寫過這麼複雜的SQL語句,所以還心存懷疑,但事實證明SQL語句可以,讓我知道了SQL的強大,不能因爲沒寫過就質疑,這一點警醒了我;
- 開始寫SQL(Hive平臺支持類SQL語句進行查詢),語句如下:
SELECT udf_fun ( concat_ws( '&', concat_ws( ',', collect_list ( commentId ) ), concat_ws( ',', collect_list ( lastChangeTime ) ) ) ) FROM ( SELECT articleId, content, commentId, lastChangeTime FROM content WHERE ( articleId, content ) IN ( SELECT articleId, content FROM Comment GROUP BY articleId, content HAVING count( * ) > 1 ) AS ccc GROUP BY articleId, content
- 執行Hive任務,在udf_fun中控制好訪問生產環境時間間隔,不要無時間間隔,可能會影響生產環境;
總結
對於4步的SQL其實還可以進行一步完善,但是我嫌麻煩,而且本來就已經產生了幾個臨時表了,再繼續增加臨時表可能會拖慢性能,所以選擇將commentId和最後修改時間連接成字符串發送給UDF,UDF再排一下序篩選一下這個方案,也是挺快的,當然選擇這種方案你得看看你的最長拼接串是多長,如果太長,http請求可能傳輸不了。