寻找具有特定子集的集合

4
我是一名物理研究生,正在编写一些代码来对几百GB的数据进行排序,并在需要时返回该数据的片段。这里的难点是,我不知道有什么好的方法可以对这种类型的数据进行排序和搜索。
我的数据基本上由大量数字集合组成。这些集合中的数字数量可以从1到n不等(虽然在99.9%的集合中,n小于15),并且大约有15 ~ 20亿个这样的集合(不幸的是,这个规模排除了暴力搜索)。
我需要能够指定一个包含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.) 数据不会改变。它们都是在一长串运行中获取的(每个运行分成2GB文件)。
2.) 至于存储空间。原始数据占用大约250GB。我估计,在处理和剥离了许多我不感兴趣的冗余元数据后,我可以将其缩小到36至48GB,具体取决于我决定保留多少元数据(没有索引)。此外,如果在数据的初始处理过程中我遇到足够多的相同集合,我可能可以通过为重复事件添加计数器而不是简单地反复重复事件来进一步压缩数据。

3.) 在处理的每个数据集中,每个数字至少包含两个数字:14位用于数据本身(检测能量),7位用于元数据(探测器编号)。因此,每个数字至少需要三个字节。

4.) 我之前的“尽管在99.9%的数据集中,n小于15”的评论是有误导性的。通过初步查看一些数据块,我发现有些数据集包含多达22个数字,但中位数为每组5个数字,平均数为每组6个数字。

5.) 尽管我喜欢构建文件指针索引的想法,但我还是有点担心,因为对于涉及多个数字的请求,我需要执行相对较慢的任务(至少我认为它很慢),即查找所有列表共同的指针集合,即查找给定数量集合的最大公共子集。

6.) 就我可用的资源而言,在将原始数据存储到系统后,我可以调动约300 GB的空间(该系统上剩余的配额)。该系统是一台双处理器服务器,配备2个四核AMD Opterons和16 GB内存。

7.) 是的,0可能出现,这是数据采集系统的一个产物,但它确实可能出现。


底层数据更改的频率有多高,如果有的话?如果它不会经常发生变化,那么可以通过一些预处理方法(类似索引)来显著加快搜索速度,但这本身也需要一些时间。 - paxdiablo
另外,你们的存储限制是多少?我知道一种可以使查找非常快速的方法,但我们需要大约3800G的初始估计,不一定在一个文件系统上。再次强调,这取决于数据的动态性。 - paxdiablo
来自Gammasphere的数据带有大量的元数据,这里提到的两字节数字是探测器的通道号码,我所需的唯一元数据是与之相关联的探测器编号,但还有很多其他的东西。 - James Matta
此外,数据存储无法像最佳解决方案那样高效,因为各个集合之间都混在一起,所以需要大量的头部信息来保持分离。事件的头部可能占据了整体空间的10%左右。 - James Matta
每个事件的元数据占据了大约80%的空间,而集合中的数字本身仅占10%的空间。并不是数据存储格式低效,我只是描述了原始数据中的基本要素。 - James Matta
显示剩余2条评论
6个回答

12

你的问题与搜索引擎面临的问题相同。“我有成千上万份文件,我需要包含这组数字的文件。”与单词不同的是,你很方便地拥有整数,而且文件规模较小。解决方案是使用倒排索引。Manning等人所著的《信息检索导论》在该链接中可免费在线阅读,非常易于理解,并详细介绍了如何实现。

你将不得不付出硬盘空间的代价,但它可以并行处理,并且一旦索引构建完成,其速度应该足够快以满足你的时序要求。


1
唯一需要补充的是,Manning等人在索引压缩方面有一章非常适用于这里 - 不要跳过它。 - SquareCog
感谢提供书籍链接,我已经阅读了一些在线版本,并且很喜欢它,因此我决定购买。这本书将与Knuth的《计算机程序设计艺术》、Stroustrup的《C++程序设计语言》和Jossuttis的《STL源码剖析》放在一起,成为我的主要参考资料。 - James Matta
1
如果你想阅读的话,你也可以看一下这个链接:http://portal.acm.org/citation.cfm?doid=1132956.1132959 - SquareCog

2
假设0-16383随机分布,每组固定15个元素,有20亿组,则每个元素将出现在大约180万组中。您是否考虑过(并且是否具备能力)构建一个16384x〜1.8M(30B条目,每个4字节)的查找表?有了这样一个表,您可以查询包含(1)、(17)和(5555)的集合,然后找到这三个约180万元素列表的交集。

我并不完全确定查找表是正确的方法,原始数据本身占用大约265GB的空间,经过初步处理后可能会占用230~250GB的空间(原始格式浪费空间且包含很多无关信息),所以查找表的大小将是数据大小的一半。 - James Matta
说实话,查找索引已经在我脑海中出现了,如果没有更好的建议,那么这可能是我的方法,使用一个索引到索引的索引,以便我可以跳转到索引内正确的位置。 - James Matta

2

我的猜测如下。

假设每个集合都有一个名称、ID或地址(如果只有20亿个,则4字节的数字就足够了)。

现在遍历所有集合一次,并创建以下输出文件:

  • 一个包含所有包含“1”的集合的ID的文件
  • 一个包含所有包含“2”的集合的ID的文件
  • 一个包含所有包含“3”的集合的ID的文件
  • ...等等...

如果每个集合有16个条目,那么平均每个这样的2^16个文件将包含2^20个集合的ID;每个ID为4字节,这将需要2^38字节(256 GB)的存储空间。

在处理请求之前,您将执行上述操作一次。

当您收到请求时,请按以下方式使用这些文件:

  • 查看请求中的几个数字
  • 打开相应的索引文件
  • 获取存在于这些文件中的所有集合的列表(每个文件中只有一百万个ID,因此这不应该很困难)
  • 查看这些少数集合中满足请求其余部分的集合

我的猜测是,如果您按照上述方法操作,创建索引将会(非常)慢,处理请求将会(非常)快。


2

我最近发现了使用空间充填曲线将多维数据映射到单个维度的方法。然后可以基于其一维索引对数据进行索引。通过找到与表示曲线的框相交的曲线段,可以轻松执行范围查询并检索这些段。

我认为这种方法比建议的疯狂索引要优越得多,因为经过研究后,索引将和我希望存储的数据一样大,这几乎不是好事情。可以在以下网页找到更详细的解释:

http://www.ddj.com/184410998

http://www.dcs.bbk.ac.uk/~jkl/publications.html


1

创建16383个索引文件,每个文件对应一个可能的搜索值。对于输入集合中的每个值,将该集合的起始位置写入相应的索引文件中。每个索引文件中包含的数字必须是相同的。现在,每个索引文件都将包含主文件中升序排列的索引。

要进行搜索,请开始读取与每个搜索值对应的索引文件。如果您从另一个文件中读取的索引比当前读取的索引低,则丢弃它并读取另一个索引。当您从所有文件中获取相同的索引时,这就是匹配项-从主文件中获取集合,并从每个索引文件中读取新的索引。一旦到达任何一个索引文件的末尾,搜索结束。

如果您的值均匀分布,则每个索引文件将包含1/16383的输入集合。如果您的平均搜索集合由6个值组成,则您将对原始输入的6/16383进行线性遍历。这仍然是O(n)解决方案,但现在n稍微小了一些。

P.S. 零是否为不可能的结果值,还是您真的有16384种可能性?


我看到你在我思考的时候已经选择了另一个解决方案。嗯,好吧。 - Mark Ransom
你的解决方案与我选择的方案相似,而Jay推荐的书籍填补了两种方法中的一些空白。现在我正在考虑如何减小数据和索引所需的大小。需要设计某种结构来消除数据中的一些冗余。 - James Matta
是的,确实如此。0会出现,这是一个数据采集系统的问题,但它确实存在。一些非零值将被传输,但会被某些防止不需要信号经过的机制所否决。不幸的是,如果计数率很高,有时会记录到结果为零的情况。 - James Matta

0

只是为了支持一种包括暴力搜索和索引查找的方法而进行的辩护:

  1. 创建一个包含集合的最小值、最大值和元素数量的索引。
  2. 然后应用暴力搜索,排除最大值<被搜索集合的最大值和最小值>被搜索集合的最小值的集合。
  3. 在暴力搜索中还要排除元素计数少于被搜索集合的元素计数的集合。

你的95%搜索实际上只是在暴力搜索一个非常小的子集。这只是一个想法。


子集会更小,但你为什么认为95%的时间它会非常小呢?我猜你通常只会排除约75%的20亿个集合,这仍然太多了。 - ChrisW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接