kdbq-并行保存分区

kdbq-并行保存分区,kdb,Kdb,我有一个函数“检索”(在本例中只是创建)一个表并将其存储在一个新分区中 npertable:100000; dbname:`:partdb; newpart:{[date] firstofmonth:"d"$"m"$date; table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100); table:`date`acc x

我有一个函数“检索”(在本例中只是创建)一个表并将其存储在一个新分区中

npertable:100000;
dbname:`:partdb;

newpart:{[date]
    firstofmonth:"d"$"m"$date;
    table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100);
    table:`date`acc xasc table;
    partname:`$(("/" sv (string dbname;string "m"$date;enlist "t")),enlist "/");
    partname set .Q.en[dbname;table];
 };
让我们假设在函数内部创建
需要“很长”的时间(例如,很多行)。现在,我不能在不同的线程上使用这个方法

newpart peach 2018.03.01 2018.04.01 2018.05.01

因为

ERROR: 'noupdate: `. `sym
这并不奇怪,因为它可能无法异步更新sym文件

在kdb中有没有一种并行存储分区的方法


感谢您的帮助

您可以做到这一点,但这取决于您在写下之前了解所有可能的符号。如果,看起来,这些是某种帐户ID,我想在保存之前,您很可能知道所有可能的值。在这种情况下,您可以首先在主线程中创建sym向量,然后执行写操作,使用运算符执行枚举,这不会更新全局变量。例如:

npertable:100000;
dbname:`:partdb;
sym:`C123`C132`C321`C121`C131;    //create sym vector
(` sv dbname,`sym) set sym;       //save sym vector in db

newpart:{[date]
    firstofmonth:"d"$"m"$date;
    table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100);
    table:`date`acc xasc table;
    partname:`$(("/" sv (string dbname;string "m"$date;enlist "t")),enlist "/");
    table:@[table;`acc;`sym$];    //enumerate acc column with hardcoded column name
    partname set table;           //table already enumerated, don't use .Q.en
 };

newpart peach 2018.03.01 2018.04.01 2018.05.01
请注意,在这种情况下,要枚举的列名是硬编码的-在更灵活的实现中,您可以使用
.Q.en
的一些修改来标识需要枚举的列,并自动对所有必要的列执行此操作


当然,如果在real
newpart
函数中有可能将新值添加到
acc
字段中,这会带来更大的问题。理想情况下,在执行
peach
之前,您希望了解主线程中的任何新值,以便可以将任何新值添加到
sym
向量中。

另一种方法是重新逻辑您的函数,并将其分解为更小的步骤。我首先将枚举与磁盘设置分开,这样可以在主线程中枚举所有表的sym列,然后在线程中将枚举数据设置为磁盘。注意-这可能只有在您首先并行化磁盘io时才有用

npertable:100000;
dbname:`:partdb;

createTab:{[datep]
    firstofmonth:"d"$"m"$datep;
    table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100);
    delete date from `date`acc xasc table
    };

createPath:{[datep]
    .Q.dd[dbname;(datep;`t;`)]
    };

enumTab:{[t]
    .Q.en[dbname;t]
    };

setInParallel:{[datep]
    enummedTabs:{enumTab createTab x} each datep;
    paths:createPath each datep;
    .[set;] peach flip (paths;enummedTabs)
    };
现在,您可以对日期列表运行setInParallel

bash> q code.q -s 5
q)setInParallel .z.d-til 5
`:partdb/2018.04.25/t/`:partdb/2018.04.24/t/`:partdb/2018.04.23/t/`..
需要注意的是:

  • 将表设置为日期分区时,不需要日期列。您当然可以拥有它,但是当q映射到日期目录中时,它就变成了虚拟日期列,因此不需要它。因此,我删除了创建时的日期列

  • .Q.dd
    是一个非常有用的函数,用于创建路径(比构建字符串更容易)。请注意我是如何从根hdb、日期参数、表名和前导`(在创建路径时表示前导/(即dir)创建路径的)

  • 我从
    newpart
    函数中获取的
    createTab
    函数。您将输入的日期强制转换为一个月,然后返回到一个日期以获取该月的第一个日期。这可能是您正在寻找的,但您知道,您将永远无法设置为月初以外的日期,例如,即使您输入的参数为2018.01.02

嗯,,
Sean

EDIT-发现Kx的一篇较旧的在线帖子,这篇帖子表明我下面的方法不是一个好主意:“不能在线程之间同时使用句柄,因为套接字描述符周围没有锁定”。但我会把它放在这里作为参考

也许可以(尽管我还没有完全测试过)设置一个单独的writer进程来处理写操作,然后将数据发送给writer,writer将依次进行枚举和写操作。大致如下:

{neg[h](`runThisFunc;onThisData);(neg h)[]} peach 1 2
我认为需要冲洗。kdb的较新版本可以允许通过IPC发送大量数据,这样部分就不会出现问题

再一次,我从来没有在生产环境中这样做过,但理论上我想不出你为什么不能