如何远程更新本地表?

时间:2019-04-10 14:11:14

标签: kdb

我在远程服务器上有一个大表,其中的数据行数未知(百万)。我希望能够一次获取100,000行的数据,用获取的行更新本地表,并完成此过程,直到获取所有行。有没有办法可以远程更新本地表?

目前,我在服务器上有一个名为t的虚拟表,以及以下变量...

t:([]sym:1000000?`A`B`Ab`Ba`C`D`Cd`Dc;id:1+til 1000000)
selector:select from t where sym like "A*"
counter:count selector
divy:counter%100000
divyUP:ceiling divy

和客户端上的以下函数以及变量index设置为0和normTable,它们是远程表的副本...

index:0
normTable:h"0#t"

batches:{[idx;divy;anty;seltr]
    if[not idx=divy;
    batch:select[(anty;100000)] from seltr;
    `normTable upsert batch;
    idx+::1;
    divy:divy;
    anty+:100000;
    seltr:seltr;
    batches[idx;divy;anty;seltr]];
    idx::0}

我使用以下命令调用该函数...

 batches[index;h"divyUP";0;h"selector"]

这种方法的问题是h"selector"同时获取所有行的数据(并多次提取-对于每十万份向我本地normTable提交的数据)。

我可以将batches函数移至远程服务器,但是如何远程更新本地normTable

或者,我可以将这些行在服务器上分成几批,然后分别提取每批。但是,如果我不知道有多少行,那我怎么知道需要多少个变量?例如,下面的方法会起作用,但最多只能显示前40万行...

batch1:select[100000] from t where symbol like "A*"
batch2:select[100000 100000] from t where symbol like "A*"
batch3:select[200000 100000] from t where symbol like "A*"
batch4:select[300000 100000] from t where symbol like "A*"

是否可以设置一个batchX变量,以便它创建一个等于divyUP计数的新变量?

3 个答案:

答案 0 :(得分:3)

在您尝试连接到远程服务器时,我建议您进行一些更改:

  • 请勿运行同步请求,因为这会使服务器减慢其处理速度。尝试使用callbacks发出异步请求。
  • 不要在每个正则表达式专用的调用中进行全表扫描(以进行大量比较)。很有可能大多数数据在下一次调用时都可以在缓存中使用,但仍不能保证会再次影响服务器的正常运行。
  • 请勿突发发送数据请求。使用计时器或在最后一批数据到达时再调用另一个数据请求。

以下方法基于上述建议。这样可以避免在整个表中扫描除索引列(重量轻)以外的其他列,并且仅在最后一批到达时才发出下一个请求。

创建批处理功能

此功能将在服务器上运行,并使用索引从表中读取一小批数据并返回所需的数据。

q) batch:{[ind;s] ni:ind+s; d:select from t where i within (ind;ni), sym like "A*"; 
                  neg[.z.w](`upd;d;$[ni<count t;ni+1;0]) }

它需要2个参数-起始索引和批处理大小。

此函数最终将异步在本地Macine上调用upd函数,并将传递2个参数。

  • 从下一个批处理开始的表索引(如果所有行都已完成以停止下一个批处理,则返回0)
  • 当前批次请求中的数据

创建回调功能

批处理功能的结果将进入该功能。

如果索引> 0,则意味着有更多数据要处理,下一批应从该索引开始。

q) upd:{[data;ind] t::t,data;if[ind>0;fetch ind]}

创建Main函数以启动过程

q)fetch:{[ind] h (batch;ind;size)}

最终打开连接,创建表变量并运行fetch函数。

q) h:hopen `:server:port
q) t:()
q) size:100
q) fetch 0

现在,以上方法基于服务器表是静态的假设。如果要实时获取更新,则需要根据服务器上表的更新方式进行更改。

此外,还可以根据远程表上设置的属性来进行其他优化,以提高性能。

答案 1 :(得分:1)

如果可以发送同步消息,可以将其简化为:

{[h;i]`mytab upsert h({select from t where i in x};i)}[h]each 0N 100000#til h"count t"

您可以轻松地对其进行更改,以控制批次的数量(而不是大小),而不是使用10 0N#(可以分10批完成)

答案 2 :(得分:1)

cut函数可以将选择结果拆分为100000行的块,而不是使用单个变量。索引每个元素是一个表。

batches:100000 cut select from t where symbol like "A*"