大資料查重去重方案及效能優化

2021-08-21 02:32:22 字數 2548 閱讀 5563

最近做針對百萬級別的資料的去重工作,現抽空寫下筆記。

做這個去重,是基於前同事的基礎上做改造,原來是用的simhash演算法做文字相似計算,上網查了下,simhash演算法是相對來說,在大資料領域比較受歡迎的查重演算法,話不多說,來一步步說下我的設計之路。

一、先簡單介紹下simhash.

傳統的hash演算法只負責將原始內容盡量均勻隨機地對映為乙個簽名值,原理上僅相當於偽隨機數產生演算法。傳統的hash演算法產生的兩個簽名,如果原始內容在一定概率下是相等的;如果不相等,除了說明原始內容不相等外,不再提供任何資訊,因為即使原始內容只相差乙個位元組,所產生的簽名也很可能差別很大。所以傳統的hash是無法在簽名的維度上來衡量原內容的相似度,而simhash本身屬於一種區域性敏感雜湊演算法,它產生的hash簽名在一定程度上可以表徵原內容的相似度。

「你媽媽喊你回家吃飯哦,回家羅回家羅」 和 「你媽媽叫你回家吃飯啦,回家羅回家羅」。

通過simhash計算結果為:

1000010010101101111111100000101011010001001111100001001011001011

1000010010101101011111100000101011010001001111100001101010001011

通過傳統hash計算為:

二、具體的應用

2.1 改造前

好了,基本要用的演算法有了,接下來就是如何好好利用這個演算法,設計乙個合理的功能。

一開始我採用的設計是,分批次遍歷所有的資料,使用simhash演算法,將資源中的文字計算為simhash簽名,並將簽名分成4段long,用這4個long片段去資源指紋分析表中用查詢比對資料,將所有4個片段中有乙個相似的指紋全部取出做海明距離的計算,海明距離小於3的再對文字做相似度計算,得出相似度最大的資源所屬的堆號,標記當前資源與其堆號相同,入庫。

這樣最後分出來的結果就是,相似的資料堆號相同,也就是把所有的資料分成一批一批的,同批的是長得差不多的。

光文字有點難懂,下面上邏輯流程圖。

根據上面這個思路,進行開發,完成後實際測試中發現,這樣設計存在嚴重的效能問題。因為資料量大,要做多次的資料庫讀取,資料庫插入,資料庫查詢,所消耗的效能是非常巨大的。經過初步計算,400w條資料,可能就需要跑25小時以上。所以,這個方案,就直接否掉了。

2.2 改造後

問題

那麼,在大資料的時代,效能是非常重要的,怎麼解決,也是很頭疼,下面我再講講我具體的解決方案,不敢說是最好的,但至少相對來說,把效能提高到一條資料大概2ms左右吧。

基於原有的分堆思路,也就是最後的目的是把相似的資料標記上乙個相同的堆號。

那麼首先,考慮到的乙個問題就是,資料的simhash指紋,如何維護的問題,當對資料做修改的時候相應的simhash應該重新計算。

其次,考慮到效能問題,像做simhash簽名和重複分析,其實是兩件事,是可以分開來做的,也就是,至少這樣,可以把效能壓力分散開來。

再來,就是多次讀取資料庫的問題。

一,要多次讀取目標資料;

二、要多次查詢分析表,來與當前目標資料做對比,以確定重複物件。

對應的解決方案

針對問題二,考慮到要多次查詢,光來回的資料庫連線互動就非常耗時,更何況還要做查詢,即使加了索引做查詢,資料量大的時候也是非常慢的。怎麼解決?

這個時候,就得在記憶體跟效能之間權衡。乙個simhash存成string型別,加上4個long,400w條資料其實也就幾百m的事,所以當然是選擇放在記憶體裡面等候做對比。

但是,使用for+if來做對比?那就真的是浪費記憶體還耗效能了。

於是我考慮到用hashmap的鍵值查詢,hashmap的鍵值查詢,很好的結合了陣列和鍊錶的優勢,可以說查詢速度是相當相當快的了。

用4個simhash片段作為key,對應的完整的simhash+堆號作為value。在對比的時候進行map.get("key1"),這樣就可以在記憶體中,快速的完成大資料之間的對比。比雙for迴圈這種蠢方法不知道快了多少個等級。

這裡我為什麼是把simhash切成4個片段而不是3個、5個、6個?

這個要根據自己伺服器的能力決定了,片段約多準確率越高、但是相對的就越佔記憶體跟耗效能。

通過dbcursor游標和hashmap的使用,其實已經在很大程度上調整了效能問題。那還有乙個入庫問題,我採用的是當積累到一定量的時候,再做批量入庫操作,這樣可以省了很多的資料庫連線時間。

MySQL 資料查重 去重的實現語句

有乙個表user,字段分別有id nick name password email phone。一 單字段 nick name 查出所有有重覆記錄的所有記錄 select from user where nick name in select nick name from user group by...

大資料查詢優化方案

1 儲存過程 2 建索引 3 分割槽 把資料分成幾個區存放,搜尋的結果合併。做表分割槽,縮小查詢範圍 按乙個有效字段分割槽,比如按月份 4 表空間 5 我們以前大資料量的解決方案是 把資料分批查出來,一次性查出來是沒有什麼好的解決辦法。6 like 必定掃全表 7 硬體 公升級伺服器,有這麼多資料的...

大資料排序,取重或去重相關問題案例

方案1 可以估計每個檔案安的大小為50g 64 320g,遠遠大於記憶體限制的4g。所以不可能將其完全載入到記憶體中處理。考慮採取分而治之的方法。s 遍歷檔案a,對每個url求取 然後根據所取得的值將url分別儲存到1000個小檔案 記為 中。這樣每個小檔案的大約為300m。s 遍歷檔案b,採取和a...