在前几篇文章中,我问了一些关于java中自定义Hash /Table编码的问题。现在,由于我不能解决它,也许我忘了正确地提到我真正想要的东西,我正在总结所有这些,以使它清楚和准确。
我要做的是:
我试图为我们的服务器编写代码,在其中我必须通过URL找到用户访问类型。
现在,我有1.1亿个URL(大约)。
所以我们所做的
1)将数据库划分为10个部分,每个部分包含1.1亿个Urls。2)使用并行数组构建HashMap,其键是URL的一个部分(表示为LONG),值是URL的另一部分(表示为INT) -键可以具有多个值。
3)然后在系统启动时,每天在HashMap中搜索其他URL(一天中保存的数百万URL)。
您尝试过的内容:
1)我尝试过许多NoSQL数据库,但是我们发现这并不适合我们的目的。
2)我已经为此目的构建了我们的custom hashmap(使用两个并行数组)。
所以,问题是什么:
当系统启动时,我们必须加载每个数据库的哈希表,并执行百万url的搜索:
现在问题是
1)虽然HashTable的性能很好,但是代码在加载HashTable时需要花费更多的时间(我们使用文件通道和内存映射缓冲区来加载它,加载HashTable需要20秒-2.2亿条目,因为加载因子为0.5,we found it most faster)
因此,我们正在花费时间:(HashTable Load + HashTable搜索)*不。= (5 + 20) * 10 = 250秒。这对我们来说是相当昂贵的,而且大部分时间( 250秒中有200秒)用于加载哈希表。
你有没有想过-其他的方法:
一种方法可以是:
不用担心加载和存储,而使用内存映射缓冲区将缓存留给操作系统。但是,由于我必须搜索数百万的密钥,它提供了比上面更糟糕的性能。
由于我们发现HashTable性能不错,但加载时间很长,因此我们想以另一种方式切断它:
1)创建大小为Integer_MAX (my own custom linked list)的链接列表数组。
2)将值(int's)插入到以键值为单位的链表中(我们将键大小缩小为INT)。
3)因此,我们只能将链接列表存储到磁盘上。
现在的问题是,创建这么多链接列表需要花费大量的时间,如果数据没有很好的分布,那么创建这么多链接列表就没有意义了。
因此,您的要求是什么::
只是我的要求:
1)具有多值插入和搜索的密钥。寻找良好的搜索性能。( 2)快速加载(特别)到内存中。
(键是64位INT,值是32位INT,一个键最多可以有2-3个值。我们也可以使我们的关键32位,但会给予更多的碰撞,但我们可以接受,如果我们能使它更好)。
有人能帮我吗,如何解决这个问题,或任何评论如何解决这个问题?
谢谢。
注:
1)根据以前关于堆栈溢出的建议,磁盘缓存的预读数据是不可能的,因为当系统启动时,我们的应用程序将开始工作,而第二天则是系统启动时。
2)我们还没有发现NoSQL db的扩展性很好,因为我们的需求很简单(这意味着只需插入哈希表键值和加载和搜索(检索值))。
3)由于我们的应用程序是一个小项目的一部分,并且要在一个小的校园中应用,我认为没有人会为此给我买一个SSD磁盘。这就是我的局限。
4)我们也使用了Guava/ Trove,但是它们也不能将如此大量的数据存储在16 GB (我们正在使用32 GB的ubuntu服务器)。
发布于 2012-08-01 19:23:24
如果您需要快速访问1.1亿个数据项,那么哈希就是方法之一。但不要重新发明轮子,用如下的方法:
发布于 2012-08-01 20:24:05
在我看来(如果我正确地理解了你的问题),你试图以一种复杂的方式来处理这个问题。
我的意思是,您试图预加载的数据是巨大的(比如说2.2亿* 64 ~14‘s)。你正试着记忆-地图等。
我认为这是一个典型的问题,是通过在不同的机器上分配负载来解决的。也就是说,您不应该试图定位链接列表索引,而应该尝试计算已加载映射特定部分的适当机器的索引,并从该机器中获取值(每台机器都加载了此数据库映射的一部分,并且每次从映射的适当部分(即计算机)获取数据)。
也许我离这里很远,但我也怀疑你在使用32位的机器。
因此,如果你必须继续使用一台机器的架构,并且经济上不可能改进你的硬件(64位机器和更多的RAM或SSD,正如你所指出的那样),我认为你不可能做出任何重大的改进。
发布于 2012-08-22 16:08:19
我真的不明白你是以什么形式将数据存储在磁盘上。如果您要存储的内容由urls和一些数字组成,您可以通过压缩数据(除非您已经在这样做)来大大加快从磁盘加载的速度。
创建一个在加载过程中解压缩的多线程加载程序可能会给您很大的帮助。
https://stackoverflow.com/questions/11765517
复制相似问题