Java – 自定义哈希映射/表格一些点

在之前的一些post中,我提出了一些关于java中自定义哈希映射/表编码的问题。 现在我无法解决它,也许我忘了正确地提到我真正想要的东西,我总结所有这些以使其清晰和准确。

我要做的是:

我正在尝试为我们的服务器编写代码,我必须通过URL查找用户访问类型。

现在,我有1110万个URL(大约)。

那么,我们做了什么,

1)将数据库划分为1.1亿个Url的10个部分。 2)使用并行数组构建HashMap,其键是URL的一部分(表示为LONG),值是URL的其他部分(表示为INT) – 键可以有多个值

3)然后在系统启动时,每天在HashMap中搜索一些其他URL(一天内保存的数百万个URL)。

你有什么尝试:

1)我已经尝试了很多NoSQL数据库,但是我们发现它不太适合我们的目的。

2)我为此目的构建了自定义hashmap (使用两个并行数组)。

那么,问题是什么:

当系统启动时,我们必须加载每个数据库的哈希表并执行搜索百万个url:

现在,问题是,

1)虽然HashTable性能非常好,但是加载HashTable时代码需要更多时间(我们使用文件通道和内存映射缓冲区来加载它,加载HashTable需要20秒–220万条入口 – 因为加载因子是0.5, 我们发现它最快 )

所以,我们花时间:( HashTable Load + HashTable Search)* DB =(5 + 20)* 10 = 250秒。 对我们来说这是非常昂贵的,并且大部分时间(250秒中的200秒)用于加载哈希表。

你有没有想过其他的方式:

一种方法是:

无需担心加载和存储,并通过使用内存映射缓冲区将缓存留给操作系统。 但是,由于我必须搜索数百万个密钥,因此它的性能会比上面提高。

由于我们发现HashTable性能不错但加载时间很长,我们认为可以通过另一种方式将其切断:

1)创建一个大小为Integer_MAX的链接列表数组( 我自己的自定义链表 )。

2)将值(int)插入到编号为密钥编号的链接列表中(我们将密钥大小减小到INT)。

3)因此,我们必须仅将链接列表存储到磁盘。

现在,问题是,创建如此数量的链接列表需要花费大量时间,如果数据分布不均,则创建如此大量的链接列表没有任何意义。

那么,你的要求是什么:

只需我的要求:

1)具有多个值插入和搜索的键。 寻找不错的搜索性能。 2)快速加载(特别)到内存中的方法。

(键是64位INT,值是32位INT,一个键最多可以有2-3个值。我们可以使我们的键32位也会产生更多的冲突,但如果我们可以做得更好,我们可以接受) 。

任何人都可以帮助我,如何解决这个或任何评论如何解决这个问题?

谢谢。

注意:

1)根据之前的Stack Overflow建议,无法预读磁盘缓存数据,因为系统启动时我们的应用程序将开始工作,并在系统启动的第二天开始工作。

2)我们还没有发现NoSQL db的扩展性很好,因为我们的要求很简单(意味着只插入哈希表键值和加载和搜索(检索值))。

3)由于我们的应用程序是小型项目的一部分并且应用于小型校园,我认为没有人会为我购买SSD磁盘。 这是我的限制。

4)我们也使用Guava / Trove,但他们也无法在16 GB中存储如此大量的数据(我们使用32 GB的ubuntu服务器。)

在我看来(如果我理解你的问题正确),你试图以一种错综复杂的方式解决问题。
我的意思是你试图预加载的数据开始时很大(比方说2.2亿* 64~14GB)。 而你正试图为此记忆地图等。
我认为这是通过在不同机器中分配负载来解决的典型问题。 即,而不是试图找到链表索引,你应该试图找出已加载地图的特定部分的相应机器的索引,并从那里获取该机器的值(每台机器已加载部分此数据库地图,您可以从地图的相应部分(即每次机器)获取数据。
也许我离开这里,但我也怀疑你使用的是32位机器。
因此,如果您必须继续使用单机架构,并且在经济上不可能改进您的硬件(64位机器以及更多RAM或SSD,如您所指出的那样),我认为您无法做出任何显着的改进。

我真的不明白你将数据存储在磁盘上的forms。 如果您存储的内容包含url和一些数字,您可以通过压缩数据来加速从磁盘加载(除非您已经这样做了)。

创建一个在加载时解压缩的multithreading加载器可能会给你带来很大的提升。