6

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

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

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

我们的倒排索引存储为:

Dictionary<string, List<ApplicationObject>>

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

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

4

7 回答 7

3

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

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

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

于 2008-10-21T14:59:16.307 回答
3

我看到了一些解决方案:

  1. 如果您在数组中有 ApplicationObjects,则只存储索引 - 可能会更小。
  2. 您可以使用一些 C++/CLI 来存储字典,使用 UTF-8。
  3. 不要费心存储所有不同的字符串,使用Trie
于 2008-10-21T15:17:08.470 回答
3

我怀疑你可能会发现你有很多非常小的列表。

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

如果这些都没有多大意义,请告诉我,我会尝试编写一些代码。

于 2008-10-21T16:01:24.933 回答
1

我同意 bobwienholt 的观点,但如果你正在索引数据集,我假设这些来自某个数据库。仅使用DTSearchLucene.net 之类的搜索引擎进行搜索是否有意义?

于 2008-10-21T15:13:50.503 回答
1

您可以采用 Lucene 所做的方法。首先,您创建一个随机访问内存流(System.IO.MemoryStream),该流镜像磁盘上的一个,但只是其中的一部分(如果您有错误的部分,请从磁盘加载另一个) . 这确实会让人头疼,您的字典需要一种文件可映射格式。维基百科对分页技术有描述。

在文件可映射的情况下。如果您打开 Reflector 并反映 Dictionary 类,您将看到它由存储桶组成。您可能可以将这些存储桶中的每一个用作页面和物理文件(这样插入速度更快)。然后,您还可以通过简单地将“项目 x 已删除”值插入文件并每隔一段时间清理文件来松散地删除值。

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

于 2008-10-22T05:41:43.827 回答
1

使用内存映射文件 Win32 API 透明地备份您的内存结构怎么样?

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

于 2008-10-22T05:50:25.477 回答
0

索引是仅添加到还是从中删除键?

于 2008-10-21T16:08:33.843 回答