我是物理专业的研究生,我正在编写一些代码来排序数百GB的数据,并在我要求时返回该数据的切片。这是诀窍,我知道没有很好的方法来排序和搜索这种数据。
我的数据基本上由大量数字组成。这些集合中可以包含1到n个数字(虽然在99.9%的集合中,n小于15),并且这些集合大约有1.5到20亿(不幸的是,这个大小排除了强力搜索)。 / p>
我需要能够指定一个包含k个元素的集合,并且每个集合都包含k + 1个或更多元素,其中包含返回给我的指定子集。
简单示例:
假设我的数据有以下几组:
(1,2,3)
(1,2,3,4,5)
(4,5,6,7)
(1,3,8,9)
(5,8,11)
如果我要提出请求(1,3),我会有一套:(1,2,3),
(1,2,3,4,5)和(1,3,8,9)
请求(11)将返回集合:(5,8,11)。
请求(1,2,3)将返回集:(1,2,3)和(1,2,3,4,5)
请求(50)将不返回任何集:
到目前为止,模式应该清晰。这个例子和我的数据之间的主要区别在于,没有我的数据的集合更大,用于集合中每个元素的数字从0到16383(14位),并且还有许多更多的集合。
如果重要的话我用C ++编写这个程序虽然我也知道java,c,一些程序集,一些fortran和一些perl。
有没有人知道如何解决这个问题?
编辑:
回答几个问题,并补充几点:
1。)数据不会改变。这一切都是在一长串的运行中进行的(每个运行分为2个gig文件)。
2.。)至于存储空间。原始数据占用大约250千兆字节。我估计在处理和剥离了许多我不感兴趣的无关元数据后,我可以将其降低到36到48千兆字节,具体取决于我决定保留多少元数据(没有索引)。另外,如果在我初始处理数据时遇到了足够多的相同集合,我可以通过添加重复事件的计数器来进一步压缩数据,而不是简单地一遍又一遍地重复事件。
p>
3.)处理集内的每个数字实际上包含至少两个数字14位用于数据本身(检测到的能量)和7位用于元数据(检测器编号)。所以我需要每个数字至少三个字节。
4。)我的“虽然在99.9%的集合中,n小于15”,但评论具有误导性。初步浏览一些数据块,我发现我的数据集包含多达22个数字,但中位数是每组5个数字,平均值是每组6个数字。
5.)虽然我喜欢构建指向文件的索引的想法,但我有点怀疑,因为对于涉及多个数字的请求,我留下了半慢的任务(至少我觉得它很慢)找到列表共有的所有指针的集合,即找到给定数量集合的最大公共子集。
6。)就我可用的资源而言,在我获得系统上的原始数据(我在该系统上的配额的剩余部分)之后,我可以集合大约300个空间。该系统是一个双处理器服务器,具有2个四核amd和16 GB的内存。
7.。)是的0可以发生,它是数据采集系统的工件,但它可以发生。
答案 0 :(得分:11)
您的问题与搜索引擎所面临的问题相同。 “我有很多文件。我需要那些包含这组文字的文件。”你只是(非常方便),整数而不是单词和小文件。解决方案是inverted index。 Manning等人的Introduction to Information Retrieval(在该链接上)免费在线提供,非常易读,并将详细介绍如何执行此操作。
您将不得不为磁盘空间付出代价,但它可以并行化,并且在构建索引后应该足够快以满足您的时序要求。
答案 1 :(得分:2)
假设0-16383的随机分布,每组具有一致的15个元素,以及20亿个集合,则每个元素将出现在大约1.8M集合中。您是否考虑(并且您是否有能力)构建16384x~1.8M(30B条目,每个4字节)查找表?给定这样一个表,你可以查询哪些集包含(1)和(17)和(5555),然后找到这三个~1.8M元素列表的交集。
答案 2 :(得分:2)
我的猜测如下。
假设每个集合都有一个名称或ID或地址(如果只有20亿个数字,则会有4个字节的数字)。
现在遍历所有集合,并创建以下输出文件:
如果每组有16个条目,则平均每个2 ^ 16个文件将包含2 ^ 20个集合的ID;如果每个ID为4个字节,则需要2 ^ 38字节(256 GB)的存储空间。
在处理请求之前,您将完成上述操作。
收到请求时,请按以下方式使用这些文件:
我的猜测是,如果你这样做,创建索引将(非常)慢,处理请求将(非常)快。
答案 3 :(得分:2)
我最近发现了使用空间填充曲线将多维数据映射到单个维度的方法。然后可以根据其1D索引对数据进行索引。通过查找与表示曲线的框相交的曲线段,然后检索这些段,可以轻松地执行范围查询。
我认为这种方法远远优于制作疯狂的索引,因为在查看之后,索引将与我希望存储的数据一样大,几乎不是一件好事。有关这方面的更详细解释可以在以下网址找到:
http://www.ddj.com/184410998
和
http://www.dcs.bbk.ac.uk/~jkl/publications.html
答案 4 :(得分:1)
制作16383个索引文件,每个可能的搜索值一个。对于输入集中的每个值,将集合开头的文件位置写入相应的索引文件中。重要的是每个索引文件包含相同集合的相同编号。现在,每个索引文件都将由升级索引组成主文件。
要搜索,请开始阅读与每个搜索值对应的索引文件。如果您读取的索引低于从另一个文件读取的索引,请将其丢弃并读取另一个文件。当您从所有文件获得相同的索引时,这是匹配的 - 从主文件获取集合,并从每个索引文件中读取新索引。一旦你到达任何索引文件的末尾,你就完成了。
如果您的值均匀分布,则每个索引文件将包含1/16383个输入集。如果您的平均搜索集包含6个值,那么您将在原始输入的6/16383上进行线性传递。它仍然是一个O(n)解决方案,但你的n现在有点小了。
P.S。零是不可能的结果值,还是你真的有1638 4 的可能性?
答案 5 :(得分:0)
只是扮演魔鬼的倡导者,采取包括暴力+索引查找的方法:
95%的搜索实际上都是强行推断一个非常小的子集。只是一个想法。