kdb - kdb q - 有效地计算平面文件中的表
问题描述
我有很多表存储在平面文件中(在一个名为 的目录中basepath
),我想检查它们的行数。我现在能做到的最好的是:
c:([] filename:system "ls ",basepath;
tablesize:count each get each hsym `$basepath,/:system "ls ",basepath)
它将每个表完全加载到内存中,然后执行计数(这很慢)。保存为张开的表格是加快速度的唯一方法(因为我只会加载 1 列并计算它)还是 q 中有一个我可以使用的技巧?
谢谢您的帮助
解决方案
如果您将 basepath 定义为存储所有平面表的目录的路径字符串,则可以创建行数字典,如下所示:
q)cnt:{count get hsym x}
q)filename:key hsym `$basepath
q)filename!cnt each filename
t| 2
g| 3
这是我在基本路径目录中保存平面表 t 和 g 的地方。这使您不必使用system
通常效率较低的命令。该函数cnt
获取每个平面表的路径(作为符号)并返回行数而不将它们保存到内存中。
如果您可以控制保存此类文件的过程,最好的解决方案是添加一个额外的步骤,即在保存原始数据的同时将行计数的元信息单独保存在某个地方。这将允许您从该文件快速访问表大小,而不是每次都读取完整的 tbale。
但是,请注意,要完全避免将它们拉入内存,您必须改为使用read1
并查看二进制数据的标头。正如您所说,最好保存为张开的表格并在一列中阅读。
更新:我不建议这样做,强烈建议执行上述操作,但出于好奇,在研究使用read1
这里的示例后,一个 hacky 解决方案可能是什么样子:
f:{
b:read1(y;0;x);
if[not 0x62630b~b[2 4 5];'`$"not a table"];
cc:first first((),"i";(),4)1:b 7+til 4;
if[null ce:first where cc=sums 0x0=11 _ b;:.z.s[x*2;y]];
c:`$"\000" vs "c"$b[11+til ce];
n:first first((),"i";(),4)1:b[(20+ce)+til 4];
:`columns`rows!(c;n);
}[2000]
q 二进制文件格式在任何地方都没有记录,唯一的方法是保存不同的东西并查看字节如何变化。它也可能在版本之间发生变化 - 以上是为 3.5 编写的,可能仅对 3.0-3.5 有效,而不是最新的 3.6 版本或任何 2.X。
给定的代码按以下方式工作:
从文件的前面读取一个块
验证它看起来像一个扁平的无键表(使用符号 [11] 键翻转 dict[99] 的 [98])
- 将列列表中的符号计数读取为 little endian 4 byte int
- 扫描以 null 结尾的字符串以查找那么多零字节
- 如果列太多或太冗长以至于我们没有将它们全部放在这个块中,它将使块的大小加倍并重试
- 把字符串变成符号
- 使用我们从列列表末尾获得的偏移量,跳过更多列的混合列表的标题
- 然后从第一列的标题中读取计数
希望这能回答你的问题!
推荐阅读
- sql - 为分组数据集选择随机值
- mongodb - 如何从单个文档中的列表中查询和获取值
- angular - 如何处理 Angular 组件中的错误
- angular - Angular Material:在高度变化时重新计算 mat-menu 的位置
- vue.js - Vue.JS:在mounted()中使用变量和axios?
- java - 让特定线程等待状态计数器达到 0
- javascript - 是否在已发布的 node_module 库中存储或不存储原始 Typescript 代码?
- python - Maven创建python conda虚拟环境
- c# - 如何忽略运行时 JSON 上的一些 DataMember
- django - 如何在 django 模型字段中存储字符串(标签或关键字)列表?