2016-11-21 78 views
6

我遇到以下問題。 我使用和API連接到某個地方,並獲取數據作爲輸入流。 的目標是在刪除重複行後保存數據。 第10,15,22列定義的重複。在大型數據庫中刪除java中的重複項

我使用多個線程獲取數據。 目前我首先將數據保存到csv文件中,然後刪除重複項。 我想在閱讀數據時做到這一點。 數據量約爲1000萬條記錄。 我有限的內存,我可以使用。該機器有32GB的內存,但我有限,因爲有其他應用程序使用它。

我在這裏讀到了關於使用哈希映射。 但我不確定我有足夠的內存來使用它。

有沒有人有建議如何解決這個問題?

+1

您是否有API的輸出示例?是由三列(10,15,22)的組合定義的重複,還是每一列都必須是唯一的,而不涉及其他列? –

+0

api的輸出是類似於這樣的字符串: =「banna」,=「orange」,=「apple」...等約30個元素。 這些列的組合是關鍵。 – mikeP

回答

0

您可以使用ConcurrentHashSet。它會自動刪除重複的元素,它的線程安全性達到一定的限制

+0

什麼是內存限制? 它會處理我擁有的數據量嗎? – mikeP

1

一個HashMap將佔用至少與原始數據一樣多的內存。因此,對於您的數據集的大小可能不太可行(但是,您應該檢查它,因爲如果它是最簡單的選項)。

我會做的是將數據寫入文件或數據庫,計算要進行重複數據刪除的字段的哈希值,並將哈希值存儲在內存中,並對文件進行適當的引用(例如,where的字節索引原始值在文件中)。當然應該儘可能小。

當您點擊哈希匹配時,查找原始值並檢查它是否相同(因爲不同值的哈希值可能會一起出現)。

現在的問題是你期望有多少重複。如果你期望幾場比賽,我會選擇一個便宜的寫作和昂貴的閱讀解決方案,即將所有東西線性地轉儲到一個平面文件中並從該文件中讀回。

如果你期望很多匹配,它可能是相反的方式,即有一個索引文件或一組文件,甚至是一個數據庫(確保它是一個數據庫,寫操作不是太昂貴)。

+0

如果我散列鍵並將其插入列表(或鏈表),並檢查列表是否存在散列,如果不存在,我將直接寫入目標文件,如果存在,我會忽略? 我除了有大約200萬個獨特的記錄。 – mikeP

+0

正如@lexicore所提到的那樣,您可能有散列衝突,即兩個不同的值可能具有相同的散列。如果你可以爲你的用例提供一個特殊的散列函數來保證避免散列衝突,那麼你可以做你所描述的。否則,一旦你找到一個相同的散列,你必須比較實際的基礎值。 一個例外將是一個用例,其中可以接受一些獨特的條目(一種相當不尋常的情況)。 –

1

的解決方案取決於有多大的15列10,你的數據,22

假設它不是太大(比如,約1KB),實際上你可以實現一個內存解決方案。

  • 實現一個Key類從15個列10,存儲值,22.小心地實施equalshashCode方法。 (您也可以使用正常的ArrayList。)
  • 創建一個Set,它將包含您讀取的所有記錄的密鑰。
  • 對於您閱讀的每條記錄,請檢查它是否已在該集合中。如果是,請跳過該記錄。如果不是,寫入記錄輸出,將密鑰添加到集合中。確保您以線程安全的方式進行設置。

在最糟糕的情況下,您需要number of records * size of key內存量。對於10000000個記錄和假設的<每個密鑰1kb,這應該在10GB左右工作。

如果密鑰大小仍然過大,您可能需要一個數據庫來存儲密鑰集。

另一種選擇是存儲密鑰的散列而不是全部密鑰。這將需要更少的內存,但你可能會得到散列衝突。這可能會導致「誤報」,即錯誤的重複,這些重複實際上並不重複。爲了完全避免這種情況,你需要一個數據庫。