如何优化大内存数据库的分页

时间:2010-06-07 13:36:50

标签: c++ windows database memory-management paging

我有一个应用程序,使用数据库中每个表的stl-map在内存中实现整个数据库。

stl-map中的每个项目都是一个复杂的对象,引用其他stl-maps中的其他项目。

该应用程序使用大量数据,因此它使用超过500 MB的RAM。客户端可以联系应用程序并获取整个数据库的筛选版本。这是通过遍历整个数据库并查找与客户端相关的项目来完成的。

当应用程序运行一个小时左右时,Windows 2003 SP2开始为应用程序分页RAM的部分内容(尽管机器上有16 GB的RAM)。

应用程序部分被页面调出后,客户端登录需要很长时间(10分钟),因为它现在为stl-map中的每个指针查找生成页面错误。如果在此之后第二次运行客户端登录,则它很快(几秒),因为所有内存现在都回到RAM中。

我可以看到有可能告诉Windows将内存锁定在RAM中,但这通常仅推荐用于设备驱动程序,并且仅适用于“少量”内存。

我想一个糟糕的解决方案可能是遍历整个内存数据库,因此告诉Windows我们仍然有兴趣将数据模型保存在RAM中。

我想另一个糟糕的解决方案可能是在Windows上完全禁用页面文件。

我想昂贵的解决方案是SQL数据库,然后重写整个应用程序以使用数据库层。然后希望数据库系统将实现快速访问的手段。

还有其他更优雅的解决方案吗?

6 个答案:

答案 0 :(得分:5)

声音就像是内存泄漏或严重的碎片问题。在我看来,第一步是弄清楚是什么导致500 Mb的数据耗尽16 Gb的RAM并仍然需要更多。

编辑:Windows有一个工作集修剪器,主动尝试分页空闲数据。基本思想是它通过并将页面标记为可用,但将数据保留在其中(并且虚拟内存管理器知道它们中的数据)。但是,如果您在将内存分配给其他用途之前尝试访问该内存,则会将其标记为再次使用,这通常会阻止其被分页。

如果您确实认为这是问题的根源,您可以通过调用SetProcessWorkingSetSize间接控制工作集修剪器。至少根据我的经验,这很少用,但你可能处于其中一个非常有用的特殊情况。

答案 1 :(得分:2)

正如@Jerry Coffin所说,听起来你真正的问题是内存泄漏。解决了这个问题。

但是为了记录,你的“穷人解决方案”都不会起作用。完全没有。

Windows会将某些数据分页,因为RAM中没有空间。 循环遍历整个内存数据库将加载数据模型的每个字节,是......这将导致其中的其他部分被分页。最后,您会产生很多页面错误,最终的唯一区别是 部分数据结构被分页。

禁用页面文件?是的,如果您认为硬碰撞比低性能更好。 Windows不会将数据分页,因为它很有趣。它可以处理内存不足的情况。如果您禁用了页面文件,那么应用程序只会在以其他方式分页数据时崩溃。

如果您的数据集确实太大而不适合内存,那么我不明白为什么SQL数据库会特别“昂贵”。与当前解决方案不同,数据库针对此目的进行了优化。它们的目的是处理太大而无法容纳在内存中的数据集,并且有效地完成这项工作。

听起来你有内存泄漏。修复这将是优雅,高效和正确的解决方案。

如果你不能那样做,那么

  • 在问题上投入更多内存(应用最终使用16GB?然后投入32或64GB)或
  • 切换到针对高效磁盘访问进行优化的格式(可能是SQL数据库)

答案 2 :(得分:0)

----编辑

鉴于蛇足的解释,问题是更换未使用较长时间的内存,并且由于在需要时没有内存中的数据。这与此相同:

Can I tell Windows not to swap out a particular processes’ memory?

和VirtualLock函数应该完成它的工作:

http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx

----以前的回答

首先,您需要区分内存泄漏和内存需求问题。

如果你有内存泄漏,那么将整个应用程序转换为SQL比调试应用程序要花费更多。

SQL不能比设计良好,特定于域的内存数据库更快,如果你有bug,你也可能在SQL版本中有不同的版本。

如果这是一个内存需求问题,那么无论如何你都需要切换到SQL,这听起来像是一个很好的时刻。

答案 3 :(得分:0)

我们遇到了类似的问题,我们选择的解决方案是在共享内存块中分配所有内容。 AFAIK,Windows不会对此进行分页。然而,在这里使用stl-map也不适合我们的内心,并且超出了我们的要求。

我们正在使用Boost Shared Memory为我们实现此功能,并且效果很好。密切关注示例,您将快速启动并运行。 Boost也有Boost.MultiIndex,可以做很多你想做的事。

对于免费的sql解决方案,你看过Sqlite吗?他们可以选择在内存数据库中运行。

祝你好运,听起来像一个有趣的应用程序。

答案 4 :(得分:0)

  

我有一个整个应用程序   数据库在内存中实现   使用stl-map表示每个表   数据库中。

这是结束的开始:STL的std :: map非常低效。同样适用于std :: list。每个元素都将单独分配,造成相当严重的内存浪费。我经常在可能的应用程序中使用std :: vector + sort()+ find()而不是std :: map(搜索次数多于修改次数)并且我事先知道内存使用可能会成为一个问题。

  

应用程序运行时   一个小时左右,然后是Windows 2003   SP2开始分页   应用程序的RAM(尽管如此   机器上有16 GB的RAM。

很难说不知道你的应用程序是如何编写的。 Windows具有从RAM卸载的功能,可以卸载任何空闲应用程序的内存。但这通常会影响内存映射文件等。

否则,我强烈建议您阅读Windows memory management documentation。它不是很容易理解,但Windows具有应用程序可用的各种类型的内存。我从来没有运气,但可能在你的应用程序中使用自定义std :: allocator会起作用。

答案 5 :(得分:0)

我可以相信这是有缺陷的页面文件行为的错误 - 我运行我的笔记本电脑主要是从nt4.0关闭页面文件。根据我的经验,至少在XP专业版中,Windows只是为了提供一个可疑的好处,只是为了提供一个可疑的好处,即对最大工作区空间进行真正非常慢的扩展。

询问使用16千兆位真实RAM可以实现硬盘交换的好处?如果你的工作设置得如此之大,以至于需要比+10 Gigs更多的虚拟内存,那么一旦交换实际上是必需的,过程将花费更长的时间,完成数千倍。在Windows上,无法访问的文件系统缓存似乎会对抗这些关系。

现在,当我(非常)偶尔在我的XP笔记本电脑上耗尽工作时,没有交通拥堵,这个有罪的应用程序只是崩溃了。在此之前暂停内存glugging进程并发出警报的实用程序会很好,但是没有这样的东西只是违规,崩溃,有时explorer.exe也会崩溃。

Pagefiles - 谁需要em'