繁体   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