簡體   English   中英

在Java中保存大量數據的最佳實踐

[英]Best practice for holding huge lists of data in Java

我正在用Java編寫一個小系統,我從文本文件中提取n-gram特征,然后需要執行特征選擇過程以選擇最多的鑒別器特征。

單個文件的特征提取過程返回一個映射,該映射包含每個唯一特征,它在文件中的出現。 我將所有文件的地圖(地圖)合並到一個地圖中,其中包含從所有文件中提取的所有獨特功能的文檔頻率(DF)。 統一地圖可包含10,000,000個以上的條目。

目前,特征提取過程運行良好,我想執行特征選擇,其中我需要實現信息增益或增益比。 我將首先對Map進行排序,執行計算並保存結果,以便最終得到一個列表(對於每個特征,其特征選擇分數)

我的問題是:保存大量數據(~10M)並執行計算的最佳實踐和最佳數據結構是什么?

這是一個非常廣泛的問題,所以答案也很廣泛。 解決方案取決於(至少)這三件事:

  1. 您的條目大小

存儲10,000,000個整數將需要大約40MiB的內存,而存儲10,000,000 x 1KiB記錄將需要超過9GiB。 這是兩個不同的問題。 千萬個整數在任何庫存Java集合中存儲在內存中是微不足道的,而將9GiB保留在內存中將迫使您調整和調整Java堆和垃圾收集器。 如果條目更大,比如1MiB,那么你可以完全忘記內存存儲。 相反,您需要專注於尋找一個好的磁盤支持的數據結構,也許是一個數據庫。

  1. 您正在使用的硬件

在具有8 GiB ram的計算機上存儲一千萬條1KiB記錄與將它們存儲在具有128GiB的服務器上的記錄不同。 使用前一台機器幾乎不可能的事情對后者來說是微不足道的。

  1. 您想要執行的計算類型

您已經提到了排序,因此可以想到TreeMap或者PriorityQueue之類的東西。 但這是最密集的計算嗎? 你用它來分類它們的關鍵是什么? 您是否計划根據不是關鍵的其他屬性來定位(獲取)實體? 如果是這樣,那需要單獨計划。 否則,您需要遍歷所有一千萬個條目。

您的計算是在單個線程還是多個線程中運行? 如果您可能同時修改了數據,則需要單獨的解決方案。 TreeMap和PriorityQueue等數據結構必須被鎖定或替換為並發結構,例如ConcurrentLinkedHashMapConcurrentSkipListMap

我的直覺是,您可以從最初的MapReduce范例中獲取靈感,並將您的問題划分為幾個較小但相似的問題,然后匯總這些部分結果以達到完整的解決方案。

如果您一次解決一個較小的問題實例(即文件塊),這將保證您受到此單個實例的空間要求所限制的空間消耗懲罰。

這種懶惰處理文件的方法將使您選擇的數據結構保持不變。

您可以使用緩存系統,檢查MapDB非常有效並且具有樹圖實現(因此您可以毫不費力地訂購數據)。 此外,它還提供數據存儲,以便在無法保存在內存中時將數據保存到磁盤。

// here a sample that uses the off-heap memory to back the map
Map<String, String> map = DBMaker.newMemoryDirectDB().make().getTreeMap("words");

//put some stuff into map
map.put("aa", "bb");
map.put("cc", "dd");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM