我正在查询一个大型历史数据库(HDB),以按字母字符选择记录,然后将所选记录上载到另一个kdb表中。
pullRecords:{[x]select from `ts where sym like x}
pushRecords:{[x]`newTS upsert x}
实际数据库包含数百万行的记录。如果我同时为每个字符运行此命令,则会导致abort error
,因为它需要的内存多于可用内存。
下面为我设置的ts
和newTS
表。我还建立了一个名为metaTable
的元数据表,该表具有一个flag column
来指示查询何时完成运行...
ts:([]sym:1000000?`A`Ab`B`Bc`C`Ca`X`Xz`Y`Yx`Z`Zy;price:1000000?100.0;num:til 10000
newTS:([]sym:`$(); price:`float$(); amt:`int$())
metaTable:([id:`char$()]flag:`boolean$())
基于flag column
的值,我想停止脚本的运行。如果找到值1b
,则表示脚本已锁定在该字符上,并且其他字符都无法运行其查询,直到将锁定重置为负布尔值为止。如果所有值都等于0b
,则检查flag column
的字符将获得锁(将值更新为1b
)并运行其功能。查询完成后,锁将被重置。
我想做的是以下...
(1)声明2个变量。
setflag:1b
resetflag:0b
(2)检查metaTable
中的标志列,如果为0b,则设置为1b。
if[select flag from metaTable where id like "A*"=resetflag;update flag:setflag from metaTable where id="A";'"Flag set"]
if[select flag from metaTable;'"Flag already set for char "A""]
(2a)上面的操作失败,并带有type error
。我可以将选择查询存储在变量中,然后将其索引到变量中,但是一旦设置了更新后的值,它就不会返回。
chkflg:select flag from metaTable
if[chkflg.flag[0];...]
(3)运行pullRecords
查询,计算字符提取的数据行,运行pushRecords
查询。
if[select flag from metaTable;pulled::pullRecords["A*"];'"Pulling data"]
amt:count pulled
if[select flag from metaTable;pushRecords[pulled];'"Pushing data"]
(4)检查从ts
提取的数据量等于推送到newTS
的数据量。如果是这样,请将metaTable
中的标志从1b
更新为0b
。解锁脚本并开始下一个角色的过程。
if[amt~count select from newTS where sym like "A*";update flag:resetflag from `metaTable where id="A";'"Lock released"]
答案 0 :(得分:2)
您正在寻找类似于交易行为的内容。您可以在不使用metaTable的情况下执行此操作。您可以使用全局变量(或命名空间中的变量)作为锁。
下面是在主服务(正在处理并发请求的服务)上设置的示例模板。根据您的设置进行修改。
定义2个全局变量-lock(boolean)用作lock和lock_char存储当前锁定的字符。
q) lock:0b
q) lock_char:""
定义一个函数,该函数将首先检查是否可以获取锁(锁值= 0b)。如果是,则获取锁并执行其余操作,否则显示该消息并返回。
q) transaction:{[ch] if[lock;show "Currently locked for character:",lock_ch;:0b];
/ else acquire lock and perform other operations
`lock set 1b; `lock_char set ch; s:ch,"*";
`newTs upsert t: select from ts where sym like s;
if[not count[t]=count select from newTs where sym like s;call_roolback_function[]];
/ reset lock
`lock set 0b; `lock_char set "";
:1b;
}
通话功能:
q) transaction "A"