更新kdb中磁盘上的序列化表

问题描述 投票:0回答:1

我在磁盘上有一个序列化表,我想根据条件进行更新。一种方法是,将表加载到内存中,对其进行更新,然后再次在磁盘上对其进行序列化。例如:

q)`:file set ([] id:10 20; l1:("Blue hor";"Antop"); l2:("Malad"; "KC"); pcd:("NCD";"FRB") );
q)t:get `:file;
q)update l1:enlist "Chin", l2:enlist "Gor" from `t where id=10;
q)`:file set t;

我尝试直接在磁盘上更新表,但收到类型错误:

q)update l1:enlist "Chin", l2:enlist "Gor" from `:file where id=10
'type
  [0]  update l1:enlist "Chin", l2:enlist "Gor" from `:file where id=10

有没有一种方法可以直接在磁盘上更新表?(在一种情况下,我们没有足够的主内存来加载序列化的表)

kdb
1个回答
0
投票

如果将表另存为一个平面文件,则必须将整个表加载,更新然后记下来,这需要足够的内存来容纳整个表。为了避免这种情况,您可以通过在文件路径中添加尾随/来展开表格,例如

`:file/ set ([] id:10 20; l1:("Blue hor";"Antop"); l2:("Malad"; "KC"); pcd:("NCD";"FRB") );

如果存在符号列,则需要使用.Q.en。进行枚举。

这将垂直拆分表,并将列保存为单独的文件,位于文件目录下。将列保存为单独的文件后,您只能加载所需的列(而不是整个表),从而减少了内存需求。您只需要在选择查询中指定所需的列即可。

https://code.kx.com/q4m3/14_Introduction_to_Kdb%2B/#142-splayed-tables

您可以通过分区进一步水平分割数据,如果单个列太大,则会再次产生较小的子集。

https://code.kx.com/q4m3/14_Introduction_to_Kdb%2B/#143-partitioned-tables

运行时

get`:splayedTable

此内存映射表,假设您的列是可映射的,而不是将其复制到内存中,如.Q.w []显示>

您可以做

tab:update l1:enlist "Chin", l2:enlist "Gor" from (select id, l1,l2 from get`:file) where id=10
`:file/l1 set tab`l1
`:file/l2 set tab`l2

如果仅将查询所需的列加载到内存中仍然太大,则可以一次加载一列。首先装入id并找到所需的索引(其中id = 10),从内存中删除id,装入l1并使用索引进行修改,

@[get`:file/l1;indicies;:;enlist"Chin"]

写下来,然后从内存中删除。然后对l2执行相同操作。这样,您最多可以在内存中存储一​​列。理想情况下,将对表进行适当的分区,以便可以将数据保存在内存中。

您还可以直接更新磁盘上的向量,例如,避免了重写整个文件,

ind:exec i from get`:file where id=10

@[`:file/l1;ind;:;enlist"Chin"]

尽管下面的链接中提到了文件的一些限制https://code.kx.com/q/ref/amend/#functional-amend

© www.soinside.com 2019 - 2024. All rights reserved.