应用程序的内存中搜索索引占用太多内存 - 任何建议

本文关键字:内存 太多 任何建 索引 搜索 应用程序 | 更新日期: 2023-09-27 17:47:21

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

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

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

我们的倒排索引存储为:

Dictionary<string, List<ApplicationObject>>

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

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

应用程序的内存中搜索索引占用太多内存 - 任何建议

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

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

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

我看到一些解决方案:

  1. 如果数组中有应用程序对象,则仅存储索引 - 可能更小。
  2. 您可以使用一些 C++/CLI 来存储字典,使用 UTF-8。
  3. 不要费心存储所有不同的字符串,使用 Trie

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

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

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

我同意bobwienholt的观点,但是如果您正在索引数据集,我认为这些数据集来自某处的数据库。只用DTSearch或 Lucene.net 这样的搜索引擎进行搜索是否有意义?

你可以采用Lucene的方法。首先,创建一个随机访问内存流 (System.IO.MemoryStream),此流镜像磁盘上的流,但仅镜像其中的一部分(如果您有错误的部分,请从磁盘加载另一个)。这确实会引起一个头痛,您需要为字典提供文件可映射格式。维基百科有关于分页技术的描述。

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

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

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

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

索引

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