如何在数据结构中压缩许多字符串?

时间:2013-11-28 04:59:18

标签: java string xpath data-structures compression

我有一个500GB的XML文档集合,我正在编制索引。我目前只能用32GB的RAM索引6GB的这个集合。

我的索引结构是HashMap<String, PatriciaTrie<String, Integer>>,其中第一个字符串表示一个术语,第二个字符串的格式为filepath+XPath,最后一个整数表示出现次数。

我使用trie来减少共享前缀,因为我需要对数据进行排序。它对压缩有所帮助,但还不够。

此数据结构中filepath+XPath字符串的总集合介于1TB和4TB之间。我需要能够将这个数据结构完全压缩到内存中。目标机器具有256GB RAM和16个CPU内核。较少的内存有多个附加好处(例如减少冷启动时间)。索引时间并不是一件大事。

XPath代表大约250种节点类型。

我目前正在开发的方法将根据下一个可能出现的标记为每个系列的2个标签构建一个Huffman表。通常,这会将选项减少到大约4或5,这允许将XPath编码为更短的位串,然后可以将其编码为字节。

字符串通常是40-600字节(UTF-8),我相信这应该减少文件路径前缀之后的所有内容(前三个字符,由trie压缩)到最多12个字节(最深点)在树上大约有12个节点,每个节点最差1个字符表示结构,12个字节表示索引(可变字节编码,很少有元素包含索引大于256),产生通常在范围40-64字节。

我认为这是一个很好的方法,但我想我可能会遗漏一些东西。

  • 是否有更好的方法来压缩此数据结构或进入其中的数据?
  • 人们通常如何在同一数据结构中压缩许多字符串?
  • 是否存在基于整个集合独立压缩多个字符串的现有解决方案?
  • 在字符串处于这样的数据结构之后,是否有基于它们之间共享的结构来压缩尝试的好方法?

1 个答案:

答案 0 :(得分:1)

我认为你最大的问题是你每个学期都要存储太多数据。你没有说你有多少独特的术语或者有多少单个文件,但我会给出一些示例数字。

假设您在200个不同的文件中拥有200,000个唯一术语。因此,每个唯一的术语都包含至少一个文件路径的权重,或40个字节。那是在你开始索引任何东西之前。

您应该能够将此数据压缩为filepath+Xpath字符串表和一个术语列表,每个术语列表都包含对该表中条目的引用。因此,例如,您可能有:

路径表:

index   Path
  1   file+xpath1
  2   file+xpath2
  3   file+xpath3
  ...
999   file+xpath999

条款

term  references
foo   1, 19, 27, 33, 297
bar   99, 864, 865
...

现在,您的路径表可能仍然太大。您首先想到的是构建一个文件表,并使路径的第一部分成为files表的索引。所以你最终得到:

文件

  1  file1.xml
  2  file2.xml
 ...
999  file999.xml

然后你的路径变成:

  1  1,xpathA
  2  1,xpathB
  3  2,xpathQ
  ...

如果之后需要更多压缩,请构建一个包含xpath术语的字符串表,并且您的路径条目将成为该表中的一系列索引。但是,你必须要小心,因为数组或列表的分配开销会使短列表变得非常昂贵。如果你走这条路线,那么你会想要将路径列表编码为一个大的二进制数组,并将其编入索引。例如。

单词列表

1 the
2 quick
3 brown
4 fox

路径

index  path
0      1(index of file),2(quick),4(fox),-1(terminator)
4      3(index of file),3(brown),-1(terminator)
7      etc . . .

Paths表只是一个大数组,如下所示:

1,2,4,-1,3,3,-1,...

这样可以最大限度地降低数据存储成本,因为不会多次存储任何字符串。您拥有的只是字符串表和对这些字符串的引用。它所需的空间大小如下:

Combined length of all file names
Combined length of all path segment terms
(number of paths) * (average path length) * (size of integer index)
(number of terms) * (average number of references per term) * (size of integer index)

在内存中构建它可能是可能的。如果不知道你有多少个别条款,很难说。如果使用单词列表,则需要文件名,路径和各个路径段的字典。但如果你有记忆,那么一次完成就可以完成。

如果在构建时没有足够的内存用于整个树,则可以加载文件名并在内存中维护路径表。当您在文件中找到每个术语时,请将其与路径引用一起写入磁盘。最终得到的磁盘文件如下:

term, path reference
term, path reference
...

使用外部排序程序按术语排序,然后浏览并组合重复项。完成后,您最终得到一个包含以下内容的文件:

File names table
Path segments table
Paths
terms

查找非常简单。找到术语,在路径表中查找每个引用,并通过索引到文件名和路径段表中来解码路径。

几年前我使用过这样的东西,效果很好。您应该能够编写一个程序来分析您的数据,以得出数字(唯一路径,文件名数,每个术语的平均引用数等)。从那里,您可以轻松确定使用此技术是否适合您。