Database design 以半可搜索但紧凑的格式存储文本

Database design 以半可搜索但紧凑的格式存储文本,database-design,search,text,compression,n-gram,Database Design,Search,Text,Compression,N Gram,我想在一些商品硬件上使用。问题是这些小型服务器无法处理需要存储的数据的大小 这让我开始思考其他大型基于文本的系统,如WordNET或搜索引擎如何处理这个问题我想知道是否有一种方法可以规范化数据,但仍然可以使其成为可搜索的格式? 回到N-Gram,我的想法是将1-Gram中的所有单词与一个ID一起存储在数据库中。然后使用该ID在+2-Gram链中创建关系,就像在社交网络中跟踪朋友关系一样-两个ID作为一行 TABLE Words { id word } TABLE TWOGRAM

我想在一些商品硬件上使用。问题是这些小型服务器无法处理需要存储的数据的大小

这让我开始思考其他大型基于文本的系统,如WordNET或搜索引擎如何处理这个问题我想知道是否有一种方法可以规范化数据,但仍然可以使其成为可搜索的格式?

回到N-Gram,我的想法是将1-Gram中的所有单词与一个ID一起存储在数据库中。然后使用该ID在+2-Gram链中创建关系,就像在社交网络中跟踪朋友关系一样-两个ID作为一行

TABLE Words
{
    id
    word
}

TABLE TWOGRAM
{
    first_word_id
    second_word_id
}

TABLE THREEGRAM
{
    first_word_id
    second_word_id
    third_word_id
}

TABLE FOURGRAM
{
    first_word_id
    second_word_id
    third_word_id
    forth_word_id
}
是否有更有效的方法以紧凑的方式存储所有这些数据?


也许可以对成对(或序列)的单词进行哈希运算,而不是压缩文本,以实现更小的存储大小,同时仍然可以像密码一样进行搜索。

处理这种情况的典型方法是将数据分块(例如2K行),将块内的数据按列分组,然后使用快速压缩算法压缩转换后的块。 节省下来的钱可能相当可观

[编辑]根据要求提供更多详细信息: 这里的目标是处理小的压缩数据块,因此有必要将内存需求保持在合理的水平。“合理”取决于您的目标系统,所以它可以是256行、2K或8K

但是,每行中都有几个字段。 因此,直接压缩不会带来显著的节约(例如,zip是“仅”x5)。 幸运的是,这些字段之间的分隔字符是众所周知的(0x09),因此可以检索每个字段的开始和结束

其思想是将所有“字段1”组合在一起,然后是“字段2”,然后是“字段3”,依此类推。如果从.csv文件提取的块是2K行,我们知道每种类型有2K个字段

然后,一个简单的快速压缩算法将在这个转换的结构上创造奇迹。相关性非常强,因为连续场往往有很多共同点。对于这样的数据,10倍的压缩比并不令人惊讶。谷歌N-Gram数据集可能会更加有利

由于您的目标是在内存中保存尽可能多的数据以进行搜索,因此建议保持每个块足够小(大约在256到8K之间),并使用非常快速的压缩/解压缩算法。这样,解压将足够快,成为算法中不重要的一部分。 例如,类似LZ4的东西提供大约1GB/s的解压缩速度

关于搜索: 这完全取决于你想搜索什么,但如果是为了找到一个精确的N-gram,那么我们就很幸运了,因为它们已经按照字典顺序排序了

在这个阶段,将每个块的第一个N-gram存储到一个表中就足够了。 当搜索一个特定的N-gram时,只需要找到它所在的块。 块的第一个N克是必需的。如上所述,解压块应该是算法中不重要的一部分

即使使用2K行的块,也可能需要存储大量的“标题N-gram”,因此一个简单的冒泡搜索可能会相当长。建议使用树或轴搜索

加载块后,仍然需要搜索它以找到合适的N-gram。可以使用与以前相同的策略(将N-gram加载到表中,并将搜索透视到表中)

而不是为每对或每对存储3600亿1Gram 2+分组-存储单词一次-然后使用较小的整数 用词来表达似乎是一个更好的选择

(我在下面总结了我的估计。)

在这里很难说整数是更好的选择。您需要更好地估计您需要多少磁盘空间、您拥有多少磁盘空间以及您能负担多少磁盘空间

统计数字告诉我们,英语单词的平均长度是5.1个字符。在你的应用程序中,这与5.1字节相同。两个字的平均长度约为10.2字节;两个整数的长度为8字节

文件编号71(随机选择)中约有6600万个2Gram。在每个条目10.2字节的情况下,这个文件大约需要673兆字节。(假设您只存储单词,而不存储计数。)对于100个2gram文件,您应该需要52到67 Gig(忽略索引)。加上50%我们的无知。100场演出将覆盖2场比赛

如果将计数与单词一起存储,则该文件为1.6 Gig,其中100个应该约为160 Gig。因此,我们有100到160个Gig的范围来存储2Gram

我将把估算索引所需的空间留给您

整数每字可节省2.2字节。但存储两个整数意味着您必须始终进行两次联接才能恢复实际数据。(为5grams存储五个整数意味着您需要五个联接才能获取真实数据。)存储单词本身不需要联接即可获取真实数据

如果您还存储计数,则可以通过将外键存储到ngram而不是使用单个单词来节省空间。所以你可以储存

ngram_id  ngram_text
--
143564    five pounds
在一张桌子里,和

ngram_id    year    match_count  page_count  volume_count 
--
143564      1999    4            3           3
143564      2000    2            2           1
143564      2001    1            1           1
143564      2002    1            1           1
143564      2003    2            2           2
143564      2004    1            1           1
143564      2005    6            6           5
143564      2006    30           21          17
143564      2007    39           37          26
143564      2008    44           41          28
另一方面

对于特定的2gram,文本需要11个字节,整数需要4个字节。每10行节省7字节,70字节。需要一个联接才能获取真实数据。对于这种方法,我估计所有2Gram大约有130 Gig,不包括提供外键的索引和表

基于6600万行的100个文件,我对存储2Gram所需空间的估计汇总。不包括索引空间和一般存储开销(根据dbms的不同,这些开销可能很大)

如今,多TB的驱动器阵列并不十分昂贵。你们都打算靠这个赚钱吗?

Googl
                           row_len  gigabytes  joins
----------------------------------------------------
words        with counts     163.2      1,077      0
two integers with counts     128.0        845    2-5

words        without counts   10.2         67      0
two integers without counts    8           53    2-5

one integer  with counts      20          132      1
one integer  without counts    4           26 (for completeness, but not really useful)