使用 kdb+ (Q) 加载大型二进制文件

Loading a large binary file with kdb+ (Q)

我有一组大文件(大约 2Gb)。 当我尝试加载它时(假设正确):

ctq_table:flip `QTIM`BID`OFR`QSEQ`BIDSIZE`QFRSIZ`OFRSIZ`MODE`EX`MMID!("ijjiiihcs";4 8 8 4 4 4 2 1 4) 1: `:/q/data/Q200405A.BIN

返回 wsfull 错误。据我所知,Kdb+ 旨在用于此类任务。

有没有办法在 运行 内存不足的情况下处理大文件(就像保留在磁盘上,即使速度较慢)?

正如 Igor 在评论中提到的(并回到问题的主题),您可以分块读取大型二进制文件并一次写入磁盘。这将减少您的内存占用,但代价是由于额外的磁盘 i/o 操作而变慢。

一般来说,字节流的分块可能更棘手,因为你可能会以不完整的消息结束一个块(如果你的块点是任意的并且消息是可变宽度的)但是在你的情况下你似乎有固定宽度的消息所以块端点更容易计算。

无论哪种方式,我经常发现循环使用 over (/) 并跟踪您最后已知的(好)索引然后在读取下一个块时从该索引开始很有用。总体思路(未经测试)类似于

file:`:/q/data/Q200405A.BIN;
chunkrows:10000;   /number of rows to process in each chunk
columns:`QTIM`BID`OFR`QSEQ`QFRSIZ`OFRSIZ`MODE`EX`MMID;
types:"ijjiiihcs";
widths:4 8 8 4 4 4 2 1 4;
{
    data:flip columns!(types;widths)1:(file;x;chunkrows*sum widths);
    upsertToDisk[data];      /write a function to upsert to disk (partitioned or splayed)
    x+chunkrows*sum widths        /return the rolling index of the starting point for the next chunk
    }/[hcount[file]>;0]

这将一直持续到最后一个好的索引到达文件末尾。您可以根据内存限制相应地调整块行大小。

最终,如果您尝试使用免费的 32 位版本处理大量数据,那么无论您做什么,您都会感到头疼。