存储数万亿的文档相似之处

时间:2014-03-06 00:19:39

标签: sql performance csv bigdata

我写了一个程序来计算一组200万个文档中的相似之处。该程序有效,但我无法存储结果。我不需要经常访问结果,但有时需要查询它们并提取子集进行分析。输出基本上如下所示:

1,2,0.35
1,3,0.42
1,4,0.99
1,5,0.04
1,6,0.45
1,7,0.38
1,8,0.22
1,9,0.76
.
.
.

第1列和第2列是文档ID,第3列是相似性得分。由于相似性得分是对称的,我不需要全部计算它们,但这仍然留给我2000000 *(2000000-1)/2≈2,000,000,000,000行记录。

包含100万行记录的文本文件已经是9MB。外推,这意味着我需要17 TB来存储这样的结果(在平面文本文件中)。

是否有更有效的方法来存储这些类型的数据?我可以为每个文档创建一行,并在第一列中删除重复的文档ID。但那只是到目前为止。那么文件格式或特殊数据库系统呢?这必须是“大数据”中的常见问题;我看过报道类似分析的论文/博客,但没有人讨论像存储这样的实际维度。

1 个答案:

答案 0 :(得分:1)

免责声明:我对此没有任何实际经验,但这是一项有趣的练习,经过一番思考后,这就是我想出的:

由于您拥有2.000.000个文档,因此您可能会遇到文档ID的整数;这使得4个字节+4个字节;比较似乎在0.00和1.00之间,我猜一个字节可以通过将0.00-1.00编码为0..100来实现。

所以你的表将是:id1,id2,relationship_value

每个记录只有9个字节。因此(没有任何开销)((2 * 10 ^ 6)^ 2)* 9/2字节是必需的,大约是17Tb。

当然,如果你只有一张基本的桌子。由于您不打算经常查询它,我认为性能不是那么大的问题。因此,您可以通过“水平”存储值来“创造性”。 简化事物,你会将值存储在200万到200万平方,每个“交点”都是一个表示坐标之间关系的字节。这“仅”需要大约3.6Tb,但维护起来会很痛苦,而且它也没有利用关系是对称的事实。

所以我建议使用混合方法,一个包含2列的表。第一列将保留'left'cocument-id(4个字节),第二列将保存一个字符串,其中包含使用varbinary在第一列中的id之上的id开头的所有文档值。由于varbinary只占用了它所需的空间,这有助于我们赢回关系对称性所提供的空间。

换句话说,

  • 记录1将有一个(2.000.000-1)字节的字符串作为第二列的值
  • record 2将有一个(2.000.000-2)字节的字符串作为第二列的值
  • record 3将有一个(2.000.000-3)字节的字符串作为第二列的值

通过这种方式,您应该可以使用类似2Tb(包含开销)的东西来存储信息。添加压缩,我很确定你可以将它存储在现代磁盘上。

当然,系统远非最佳。事实上,查询信息需要一些耐心,因为你无法处理基于集合的事情,你几乎必须逐字节扫描。这种方法的一个好处是,您可以通过在最后添加一个新字节到EACH记录字符串+ 1个额外记录来轻松添加新文档。这样的操作会很昂贵,因为它会导致页面拆分;但至少可以在不必完全重写表格的情况下完成。但随着时间的推移它会引起一些碎片,你可能偶尔需要重建一次表,以使它再次更“对齐”。啊..技术性。

选择和更新将需要一些创造性地使用SubString()操作,但没有太复杂..

PS:严格来说,对于0..100你只需要7个字节,所以如果你真的想要挤出它的最后一位,你实际上可以在7个字节中存储8个值并保存另一个300Mb,但它会使事情变得更复杂......然而,再说一遍,数据不会像人类一样可读=)

PS:这种思路完全是为了减少所需的空间,同时在更新数据方面保持实用性。我不是说它会很快;事实上,如果你要搜索关系值为0.89或以上的所有文件,系统将不得不扫描整个表格,甚至用现代磁盘扫描需要一段时间

请注意,所有这一切都是半小时头脑风暴的结果;我实际上希望有人可能会采用更简洁的方法来讨论=)