内存映射文件 IList 实现,用于“在内存中”存储大型数据集?
Posted
技术标签:
【中文标题】内存映射文件 IList 实现,用于“在内存中”存储大型数据集?【英文标题】:Memory-mapped file IList implementation, for storing large datasets "in memory"? 【发布时间】:2011-09-14 19:11:17 【问题描述】:我需要对实现为 IList 的巨大时间序列按时间顺序执行操作。数据最终存储到数据库中,但是向数据库提交数千万次查询是没有意义的。
当前内存中的 IList 在尝试存储超过 800 万个(小)对象时会触发 OutOfMemory 异常,但我需要处理数千万个。
经过一些研究,看起来最好的方法是将数据存储在磁盘上并通过 IList 包装器访问它。
Memory-mapped files(在 .NET 4.0 中引入)似乎是正确的接口,但我想知道编写一个应该实现 IList(以便于访问)并在内部处理内存映射文件的类的最佳方法是什么.
我也很想知道您是否知道其他方式!例如,我想到了一个使用 db4o 数据的 IList 包装器(someone mentionned here 使用内存映射文件作为 IoAdapterFile,尽管使用 db4o 与直接处理内存映射文件相比可能会增加性能成本)。
我在 2009 年遇到过 this question 的提问,但没有给出有用的答案或严肃的想法。
【问题讨论】:
您执行的操作是顺序的吗?还是您一次对全部数据进行操作? 访问应该是顺序的(遍历集合以执行更新),并且我还需要能够在远端删除/删除对象。 数据库是完成这项工作的正确工具。批量更新数据,避免数据库调用过多。您可能还对 map-reduce 样式处理感兴趣,以加快速度。 【参考方案1】:我找到了这个PersistentDictionary<>,但它只适用于字符串,通过阅读源代码我不确定它是为非常大的数据集设计的。
更具可扩展性(最高 16 TB)ESENT PersistentDictionary<> 使用 Windows (XP+) 中的 ESENT 数据库引擎,可以存储所有包含简单类型的可序列化对象。
Disk Based Data Structures, including Dictionary, List and Array with an "intelligent" serializer 看起来与我正在寻找的完全一样,但它在处理非常大的数据集时运行不顺畅,特别是因为它还没有使用“本机”.NET MemoryMappedFiles,并且对 32 位系统的支持是实验性的。
更新 1:我最终实现了自己的版本,该版本广泛使用了 .NET MemoryMappedFiles;它非常快,一旦我改进了它以用于更通用的用途,我可能会在 Codeplex 上发布它。
更新 2:TeaFiles.Net 也非常适合我的目的。强烈推荐(免费)。
【讨论】:
感谢您分享您的经验。我遇到了同样的问题,我想知道您是否已经在 Codeplex 上发布了您的实现。谢谢。 嗨,还没有。我目前的一个限制是所有要存储的对象都必须是值类型。如果您是这种情况(或者您可以从引用类型迁移到值类型),那么我可以在发布到 Codeplex 之前与您分享我的代码。 @ErwinMayer 我想知道您是否在某处共享了代码。对于一些大对象,我需要一个文件支持的 IList 实现。 @RahulMisra,我建议你在 Github 上查看 TeaFiles 的源代码。【参考方案2】:我看到了几个选项:
“内存中的数据库” 例如,可以通过这种方式使用 SQLite - 无需任何设置等。只需将 DLL(1 或 2)与应用程序一起部署,其余的可以通过编程方式完成 将所有数据加载到数据库中的临时表中,使用未知(但大量)的数据,我发现这很快就会得到回报(并且处理通常可以在数据库内完成,甚至更好!) 使用 MemoryMappedFile 和固定结构大小(通过偏移量进行类似数组的访问),但要注意物理内存是限制,除非您使用某种“滑动窗口”仅将部分映射到内存中【讨论】:
【参考方案3】:内存映射文件是一种很好的方法。但是如果你需要随机访问东西,它会很慢。
你最好的选择可能是在内存中保存一个固定的结构大小(如果可以的话),然后使用偏移量作为列表项 id。但是删除/排序总是一个问题。
【讨论】:
AFAIK,随机访问应该是 O(1),因为我们知道字节偏移量。以上是关于内存映射文件 IList 实现,用于“在内存中”存储大型数据集?的主要内容,如果未能解决你的问题,请参考以下文章
Performance Monitor3:监控SQL Server的内存压力