10

我有一个 KDB/Q 数据库,每天有大约 200 万条记录,消耗大约 2G 内存。在一天结束时,它会运行一些报告内容,在表之间进行连接并将结果输出到磁盘上的文件中。在计算期间,内存使用量增长到~15G。我的问题是,一旦此操作完成,内存就永远不会被释放,直到数据库重新启动它才会消耗所有 15G 内存。

我想告诉 KDB 从内存中卸载一些表(但不要删除它们),但我不想重新启动数据库,因为其他一些应用程序仍在连接到它。

有没有办法告诉 KDB 从内存中卸载一些东西?

编辑:

如果有人觉得这很有趣,我建议看看.Q.gc[]KDB 2.5+,看起来很有希望。

4

4 回答 4

10

以下是我的研究总结:

  • KDB 之前的版本。2.5 根据需要分配 64MB 内存块并且从不释放它们。它可以重用它们。
  • 最近的 KDB 版本允许.Q.gc[]按需调用垃圾收集器(KDB 使用 ref.counting btw.)
  • 当您调用一些分配大量内存的内存密集型计算(在我的情况下约为 20gB)并且您希望在计算完成后释放内存时,这尤其有用。
  • 您总是可以考虑将内存密集型脚本放入单独的 Q 进程中,以便在脚本完成后释放内存
于 2012-04-18T11:10:36.043 回答
5

这可能很明显,但除了检查您的 q 版本的垃圾收集模式之外,请确保您实际上已经摆脱了正在使用内存的内存中数据。如果您可以摆脱整个表(例如,这是一个参与计算的临时表),只需从根命名空间中删除它

delete table from`.

如果没有,您可以删除其所有行

delete from`table
于 2012-04-23T18:29:34.573 回答
4

对于将来尝试此操作的任何人,最简单的方法是:

  1. 启动一个新的 KDB 进程。
  2. 从该过程查询中选择所需的最小有限数据子集。
  3. 从该过程执行任何连接/计算/写入文件。(允许原件进行处理请求)
  4. 关闭进程,释放所有内存。

正如上面的海报所提到的,较新版本的 KDB 可以更好地释放内存,但并不完美。

我们公司网站上有一篇很好的文章详细介绍了 KDB+ 内存管理: http ://timestored.com/kdbGuides/memoryManagement

于 2013-01-18T03:22:36.203 回答
2

http://code.kx.com/q4m3/12_Workspace_Organization/#125-expunging-from-a-context

我使用了一些不同的命令。只要您的表在删除之前存储在磁盘上,就可以了。

这是创建表之前的会话。

q).Q.w[]
used| 290192
heap| 67108864
peak| 67108864
wmax| 0
mmap| 0
mphy| 8589934592
syms| 629
symw| 20704

此命令创建表,然后将其保存到磁盘。

q)t:([]10000?"ab"; 10000?5)
q)save `t
`:t

该表仍在内存中

q).Q.w[]
used| 437808
heap| 67108864
peak| 67108864
wmax| 0
mmap| 0
mphy| 8589934592
syms| 629
symw| 20704

让我们从内存中删除变量并进行垃圾收集。

q)delete t from `.
`.
q).Q.gc[]
0

现在,已使用的内存已减少到与会话开始类似的数量。

q).Q.w[]
used| 290208
heap| 67108864
peak| 67108864
wmax| 0
mmap| 0
mphy| 8589934592
syms| 630
symw| 20730
q)\v
`symbol$()
于 2017-12-27T00:02:50.720 回答