在我们的桌面应用程序中,我们使用inverted index实现了一个简单的搜索引擎。
不幸的是,我们的一些用户的数据集可能变得非常大,例如在创建反向索引之前占用大约1GB的内存。反向索引本身占用了大量内存,几乎与索引的数据一样多(另外1GB的RAM)。
显然,这会产生内存不足错误的问题,因为每个应用程序的32位Windows限制为2GB内存,或者规格较小的计算机的用户难以应对内存需求。
我们的倒排索引存储为:
Dictionary<string, List<ApplicationObject>>
这是在数据加载期间创建的,当处理每个对象时,applicationObject的键字符串和描述字存储在倒排索引中。
所以,我的问题是:是否可以在空间方式更有效地存储搜索索引?也许需要使用不同的结构或策略?或者可以创建一种CompressedDictionary?因为它存储了很多字符串,所以我希望它是高度可压缩的。
答案 0 :(得分:3)
如果它是1GB ......把它放在磁盘上。使用像Berkeley DB这样的东西。它仍然会很快。
这是一个为其提供.net接口的项目:
答案 1 :(得分:3)
我看到了一些解决方案:
答案 2 :(得分:3)
我怀疑你可能会发现你有很多很小的名单。
我建议你大致了解频率是多少 - 你的字典条目中有多少有单个元素列表,有多少有两个元素列表等等。你可以存储几个单独的字典 - 一个用于“我只有一个元素“(直接映射)然后”我有两个元素“(映射到具有两个引用的Pair结构)等等,直到它变得愚蠢 - 很可能在大约3个条目 - 此时你回到正常列表。将整个封装封装在简单的界面后面(添加条目/检索条目)。这样你就可以减少浪费的空间(主要是空缓冲区,计数等)。
如果这些都没有意义,请告诉我,我会尝试提出一些代码。
答案 3 :(得分:1)
我同意bobwienholt,但如果你索引数据集,我认为这些来自某个地方的数据库。使用DTSearch或Lucene.net等搜索引擎进行搜索是否有意义?
答案 4 :(得分:1)
你可以采取Lucene的做法。首先,您创建一个随机访问内存中的流(System.IO.MemoryStream),此流镜像磁盘上的一个,但只有一部分(如果您有错误的部分,从磁盘加载另一个) 。这确实令人头疼,你需要一个文件可映射的字典。维基百科有paging technique的描述。
在文件可映射的方案中。如果打开Reflector并反映Dictionary类,您将看到它包含桶。您可以将这些存储桶中的每一个用作页面和物理文件(这样插入更快)。然后,您可以通过简单地将“item x deleted”值插入文件来松散地删除值,并且经常清理文件。
顺便说一句,存储桶保存具有相同哈希值的值。存储的值覆盖GetHashCode()方法非常重要(并且编译器会警告您有关Equals()的信息,因此也要覆盖它)。如果你这样做,你的查找速度会显着提高。
答案 5 :(得分:1)
如何使用内存映射文件Win32 API透明地支持你的内存结构?
http://www.eggheadcafe.com/articles/20050116.asp具有启用它所需的PInvokes。
答案 6 :(得分:0)
索引是否仅添加到或是否从中删除了键?