在我们的桌面应用程序中,我们使用倒排索引实现了一个简单的搜索引擎。

不幸的是,我们的一些用户的数据集可能变得非常大,例如在创建反向索引之前占用大约1GB的内存。反向索引本身占用了大量内存,几乎与索引的数据一样多(另外1GB的RAM)。

显然,这会产生内存不足错误的问题,因为每个应用程序的32位Windows限制为2GB内存,或者规格较小的计算机的用户难以应对内存需求。

我们的倒排索引存储为:

Dictionary<string, List<ApplicationObject>>

这是在数据加载期间创建的,当处理每个对象时,applicationObject的键字符串和描述字存储在倒排索引中。

所以,我的问题是:是否可以在空间方式更有效地存储搜索索引?也许需要使用不同的结构或策略?或者可以创建一种CompressedDictionary?因为它存储了很多字符串,所以我希望它是高度可压缩的。

有帮助吗?

解决方案

如果它是1GB ......把它放在磁盘上。使用像Berkeley DB这样的东西。它仍然会很快。

这是一个为其提供.net接口的项目:

http://sourceforge.net/projects/libdb-dotnet

其他提示

我看到了一些解决方案:

  1. 如果在数组中有ApplicationObjects,则只存储索引 - 可能更小。
  2. 您可以使用一些C ++ / CLI来存储字典,使用UTF-8。
  3. 请勿打扰存储所有不同的字符串,请使用 Trie

我怀疑你可能会发现你有很多很小的名单。

我建议你大致了解频率是多少 - 你的字典条目有多少有单个元素列表,有多少有两个元素列表等等。你可以存储几个单独的字典 - 一个用于“我只有得到一个元素“ (直接映射)然后“我有两个元素” (映射到具有两个引用的Pair结构)等等,直到它变得愚蠢 - 很可能在大约3个条目 - 此时你回到正常列表。将整个封装封装在简单的界面后面(添加条目/检索条目)。这样你就可以减少浪费的空间(主要是空缓冲区,计数等)。

如果这些都没有意义,请告诉我,我会尝试提出一些代码。

我同意bobwienholt,但如果你索引数据集,我认为这些来自某个地方的数据库。使用 DTSearch Lucene.net

你可以采取Lucene的做法。首先,您创建一个随机访问内存中的流(System.IO.MemoryStream),此流镜像磁盘上的一个,但只有一部分(如果您有错误的部分,从磁盘加载另一个) 。这确实令人头疼,你需要一个文件可映射的字典。维基百科对分页技术进行了描述。

在文件可映射的方案中。如果打开Reflector并反映Dictionary类,您将看到它包含桶。您可以将这些存储桶中的每一个用作页面和物理文件(这样插入更快)。然后,您还可以通过简单地插入“item x deleted”来松散地删除值。文件的值,并经常清理文件。

顺便说一句,存储桶保存具有相同哈希值的值。存储的值覆盖GetHashCode()方法非常重要(并且编译器会警告您有关Equals()的信息,因此也要覆盖它)。如果你这样做,你的查找速度会显着提高。

如何使用内存映射文件Win32 API透明地支持你的内存结构?

http://www.eggheadcafe.com/articles/20050116.asp 有启用它所需的PInvokes。

索引是否仅添加到或是否从中删除了键?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top