我在远程服务器上有一个大表,其中的数据行数未知(百万)。我希望能够一次获取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
计数的新变量?
答案 0 :(得分:3)
在您尝试连接到远程服务器时,我建议您进行一些更改:
以下方法基于上述建议。这样可以避免在整个表中扫描除索引列(重量轻)以外的其他列,并且仅在最后一批到达时才发出下一个请求。
创建批处理功能
此功能将在服务器上运行,并使用索引从表中读取一小批数据并返回所需的数据。
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,则意味着有更多数据要处理,下一批应从该索引开始。
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*"