Java:基于磁盘的快速哈希集

时间:2010-02-27 08:48:00

标签: java hashset disk-based

我需要存储一个大的哈希集,最多可以包含大约2亿个40位值。将其存储为2亿64位值是可以接受的(尽管有2亿* 16位丢失)。

要求是:

  • 微小的内存占用(磁盘空间不是问题,内存是)

  • 快速contains(long l)add(long l)方法(比SQL快得多)

  • 嵌入式

  • 免费且没有讨厌的许可(没有Berkeley DB)。 LGPL罚款。

  • 没有误报,也没有误报,所以像基于磁盘的布隆过滤器这样的东西不是我追求的

SQL 不是我在此之后的事情。

因为我真的认为我更喜欢 fast 这样的事情(注意解决方案比SQL解决方案快得多):

Fast disk-based hashtables?

Google是否有这样的Java API?

基于磁盘的快速键/值对实现我只使用'键'吗?

还是其他什么?

我宁愿不重新发明。

3 个答案:

答案 0 :(得分:2)

如果您可以负担128 GB的磁盘,则每40位值可以存储一位。 然后,您可以使用随机访问文件来检查已设置的位或更改它。您不必插入任何值或维护索引。

答案 1 :(得分:2)

尝试sg-cdb(djb的cdb的奇怪的gizmo端口),然后用BufferedRandomAccessFile交换RandomAccessFile(在jai-imageio代码中有一个很好的。)

我正在开心写作表现。通过屋顶(因为它全部缓冲然后一举进行)。 但是,缓冲的RAF的读取性能没有改变。

我可以花时间与H2批量导入进行比较,虽然不确定但可能具有可比性。

数据库很简单:key =>值。查找仅在密钥上受支持。 键是在我的情况下(base32编码随机int + base32编码唯一int)所以该地方不应该真正帮助太多。这些值是120个随机字节的数组。

加载(sql insert)

h2,具有131MB缓存(包括刷新,不启动):

2011年5月4日11:45:10 PM test.TestH2Simple main :插入执行添加:101625 ms

数据库大小: 大约140 MB

批量大小:2000 :插入执行添加:116875 ms

批量:10000 :insertsperformed添加:70234 ms

与cdb的sg-cdb(奇怪的Gizmo)端口进行比较:

使用RandomAccessFile

: insert without flush:21688 ms,flush:30359 ms,总计:52047 ms 磁盘上文件的大小: 66.1 MB(69,315,632字节)

使用BufferedRandomAccessFile: 约6.5秒

当然,这并不是一个公平的比较,因为H2在插入期间连续刷新数据,而sg-cdb则不然。在进行比较时必须牢记这一点。将sg-cdb插入物与H2大量插入物进行比较可能是公平的

读取(sql select)

SG-CDB

:搜索:490000 完成:1304544550439:17547 ms,计数器:0

H2

:选择执行于:19579 ms

关于内存映射文件: 他们似乎并不是你想要的。 MMap文件的出色表现是当你将大约100MB或更多内容映射到内存时(我的经验)。

答案 2 :(得分:0)

我相信你需要使用B树而不是哈希表。哈希表没有良好的二级存储位置,因此您将丢失太多的磁盘I / O时间。

大多数数据库 - 无论是关系数据库 - 都将它们的索引实现为B树,所以你所说的相当于存储一个没有附加其他数据的索引。

您是否有多个进程同时更新此数据存储?