繁体   English   中英

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

[英]Java: fast disk-based hash set

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

要求是:

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

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

  • 嵌入式的

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

  • 没有误报,也没有错误否定,所以基于磁盘的布隆过滤器之类的东西不是我想要的

SQL 不是我想要的。

因为我真的认为我更喜欢这样的快速处理 (请注意解决方案比SQL解决方案要快得多):

基于磁盘的快速哈希表?

Google是否有这样的Java API?

我仅使用“键”的基于磁盘的快速键/值对实现会成功吗?

或者是其他东西?

我宁愿不重新发明。

如果您有能力购买128 GB的磁盘,则可以每40位存储1位。 然后,您可以使用随机访问文件来检查是否设置了位或对其进行了更改。 您无需插入任何值或维护索引。

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

我的写性能令人震惊。 穿过屋顶(因为它们全部被缓冲,然后一口气被提交)。 但是,缓冲的RAF的读取性能不会更改。

我可以花一些时间与H2批量导入进行比较,尽管不确定,但可以比较。

数据库很简单:键=>值。 仅在键上支持查找。 在我的情况下,这些键是(base32编码的随机整数+ base32编码的唯一整数),因此位置实际上并没有太大帮助。 值是120个随机字节的数组。

加载(SQL插入)

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

2011年5月4日晚上11:45:10 test.TestH2Simple main:执行插入操作的时间为:101625 ms

数据库大小:大约140 MB

批大小:2000:执行插入操作的时间:116875毫秒

批次大小:10000:插入执行时间:70234毫秒

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

使用RandomAccessFile:插入时不刷新:21688毫秒,刷新:30359毫秒,总计:52047毫秒磁盘上的文件大小:66.1 MB(69,315,632字节)

使用BufferedRandomAccessFile:大约6.5秒

当然,这并不是一个公平的比较,因为H2在插入过程中连续刷新数据,而sg-cdb则不是。 执行比较时必须牢记这一点。 也许公平的是将sg-cdb插入与H2批量插入进行比较

读取(SQL选择)

sg-cdb

:搜索:490000完成于:1304544550439花费:17547毫秒,计数器:0

H2

:在19579毫秒内执行选择

关于内存映射文件:它们似乎不是您想要的。 当您将大约100MB或更多的内存映射到内存时,MMap文件的出色性能(根据我的经验)。

我相信您将需要使用B树而不是哈希表。 哈希表在二级存储中的位置不佳,因此您将浪费太多时间进行磁盘I / O。

大多数数据库(无论是否具有关系)都将其索引实现为B树,因此您所谈论的是存储没有附加任何其他数据的索引的等效操作。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM