我遇到了以下设计问题:
假设我有一百万个大小约为10KB的纯文本文件。我的目标是设计一种方法来存储所有单词的索引,这样我就可以将每个单词链接到特定的文本文件以及单词在该文件中的位置。
示例:
Text file X contents: "The quick brown fox jumps over the lazy dog"
0 1 2 3 4 5 6 7 8
Text file Y contents: "Now is the time for all good men"
0 1 2 3 4 5 6 7我想大致存储以下内容:
the => {X,0}, {X,6}, {Y,2}
quick => {X,1}
is => {Y,1}
.... and so on显然,我实际上不是在索引纯文本文件,我的索引器是一个多线程C#应用程序,它将输入提取到术语“文件”、“单词”、“位置”中。我不能创建一个典型的查找表集,因为行数很容易超过20亿行。
我最初的想法是将{message,position}对存储在一个文本blob中,该文本blob使用word本身作为主键。然而,使用这种解决方案,当我的所有线程都试图用新的{message,position}对来更新"the“的一行时,我担心会有一个巨大的争用。
我被锁定在我的环境SQL Server Express 2012中,所以让我们使用我们已有的资源。我可以对数据库本身做任何事情,事实上,我的应用程序将数据库创建为正常工作流程的一部分,因此如果需要,我可以部署CLR存储过程。
想法?
发布于 2012-07-11 11:39:25
只是为了抛出一些东西,创建一个每个文件一行的表。使用xml列存储文件的单词匹配项。
第二个表是你的单词列表。通过添加交叉引用表进行反规范化,该表允许您快速定位哪些文件包含哪些单词。
现在你可以把它扔掉了。
发布于 2012-07-11 15:02:55
我会尝试像这样的东西。创建一个带有word/file-id的关联表。每条记录都有两个ids加上一个完全由0和1组成的字符串。
因此,给出您的示例:
Text file X contents: "The quick brown fox jumps over the lazy dog"
0 1 2 3 4 5 6 7 8
Text file Y contents: "Now is the time for all good men"
0 1 2 3 4 5 6 7您将获得:
WordId | FileId | Position
the | X | 100001
the | Y | 001
quick | X | 01
is | Y | 01
....(请注意,位置也可以存储为实际的位掩码,以节省空间,但我不确定在使用或更新值时,这是否不会证明不存在问题)
这个技巧是基于所谓的"Rushmore索引“,顺便说一下。
现在,要查看文件"X“中" the”和"is“之间的距离,您必须读取这两行,并计算”is“实例和" the”实例之间的零的数量。请注意,您还可以添加额外的信息,如“word在文件中的出现次数”,以使实际距离匹配更容易:
WordId | FileId | Position |Occ
the | X | 100001 | 2
the | Y | 000001 | 1
quick | X | 01 | 1
is | Y | 01 | 1
....在这种情况下,您立即知道"the“在文件X中出现了两次,而"quick”只出现了一次。这对于构造距离计数例程可能会很方便。
发布于 2012-07-12 06:02:47
对于你正在做的事情来说,DB是过度杀伤力。你有没有考虑过使用像NoSQL或者更轻的东西?您可能应该创建一些在后台更新索引的工作线程,而不是让许多线程更新它。这会减少争执。
https://stackoverflow.com/questions/11424829
复制相似问题