在 kdb 中更新磁盘上的序列化 table
Update a serialized table on disk in kdb
我在磁盘上有一个序列化的 table,我想根据条件对其进行更新。
这样做的一种方法是将 table 加载到内存中,更新它,然后在磁盘上再次序列化它。
例如:
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;
我尝试直接在磁盘上更新 table 但收到类型错误:
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
有没有一种方法可以直接在磁盘上更新序列化的 table?(在一种情况下,我们没有足够的主内存来加载序列化的 table)
如果将 table 保存为一个平面文件,则必须加载整个 table,更新然后写入,需要足够的内存来容纳完整的 table.
为避免这种情况,您可以通过在文件路径中添加尾随 / 来展开 table,即
`:file/ set ([] id:10 20; l1:("Blue hor";"Antop"); l2:("Malad"; "KC"); pcd:("NCD";"FRB") );
如果存在符号列,则需要使用 .Q.en.
对其进行枚举
这将垂直拆分 table 并将您的列作为单独的文件保存在名为 file 的目录下。将列保存为单独的文件允许您只加载所需的列而不是整个 table,从而减少内存需求。您只需在 select 查询中指定所需的列。
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
此内存映射 table 假设您的列是可映射的,而不是将其复制到内存中,如 .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 做同样的事情。这样你在内存中最多只有一列。理想情况下,您的 table 将被适当分区,以便您可以将数据保存在内存中。
您也可以直接更新磁盘上的向量,这样就避免了重新写入整个文件,例如,
ind:exec i from get`:file where id=10
@[`:file/l1;ind;:;enlist"Chin"]
虽然下面提到的文件有一些限制 link
https://code.kx.com/q/ref/amend/#functional-amend
我在磁盘上有一个序列化的 table,我想根据条件对其进行更新。 这样做的一种方法是将 table 加载到内存中,更新它,然后在磁盘上再次序列化它。 例如:
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;
我尝试直接在磁盘上更新 table 但收到类型错误:
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
有没有一种方法可以直接在磁盘上更新序列化的 table?(在一种情况下,我们没有足够的主内存来加载序列化的 table)
如果将 table 保存为一个平面文件,则必须加载整个 table,更新然后写入,需要足够的内存来容纳完整的 table. 为避免这种情况,您可以通过在文件路径中添加尾随 / 来展开 table,即
`:file/ set ([] id:10 20; l1:("Blue hor";"Antop"); l2:("Malad"; "KC"); pcd:("NCD";"FRB") );
如果存在符号列,则需要使用 .Q.en.
对其进行枚举这将垂直拆分 table 并将您的列作为单独的文件保存在名为 file 的目录下。将列保存为单独的文件允许您只加载所需的列而不是整个 table,从而减少内存需求。您只需在 select 查询中指定所需的列。
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
此内存映射 table 假设您的列是可映射的,而不是将其复制到内存中,如 .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 做同样的事情。这样你在内存中最多只有一列。理想情况下,您的 table 将被适当分区,以便您可以将数据保存在内存中。
您也可以直接更新磁盘上的向量,这样就避免了重新写入整个文件,例如,
ind:exec i from get`:file where id=10
@[`:file/l1;ind;:;enlist"Chin"]
虽然下面提到的文件有一些限制 link https://code.kx.com/q/ref/amend/#functional-amend