【发布时间】:2015-03-26 13:44:09
【问题描述】:
这个聚合多列的 kdb 查询大约需要 31 秒,而 J 需要 3 秒
有没有更快的方法在 kdb 中求和?
最终这将针对 32 位版本的分区数据库运行
/test 1 - using symbols
n: 13000000;
cust: n?`8;
prod: n?`8;
v: n?100
a:([]cust:cust; prod:prod ;v:v)
/query 1 - using simple by
q)\t select sum(v) by cust, prod from a
31058
/query 2 - grouping manually
\t {sum each x[`v][group[flip (x[`cust]; x[`prod])]]}(select v, cust, prod from a)
12887
/query 3 - simpler method of accessing
\t {sum each a.v[group x]} (flip (a.cust;a.prod))
11576
/test 2 - using strings, very slow
n: 13000000;
cust: string n?`8;
prod: string n?`8;
v: n?100
a:([]cust:cust; prod:prod ;v:v)
q)\t select sum(v) by cust, prod from a
116745
比较J码
n=:13000000
cust=: _8[\ a. {~ (65+?(8*n)#26)
prod=: _8[\ a. {~ (65+?(8*n)#26)
v=: ?.n#100
agg=: 3 : 0
keys=:i.~ |: i.~ every (cust;prod)
c=.((~.keys) { cust)
p=.((~.keys) { prod)
s=.keys +//. v
c;p;s
)
NB. 3.57 seconds
6!:2 'r=.agg 0'
3.57139
({.@$) every r
13000000 13000000 13000000
更新: 从 kdbplus 论坛,我们可以将速度差异降低到大约 2 倍
q)\t r:(`cust`prod xkey a inds) + select sum v by cust,prod from a til[count a] except inds:(select cust,prod from a) ? d:distinct select cust,prod from a
6809
更新 2:为每个 @user3576050 添加了另一个数据集 该数据集的总行数相同,但每组分布 4 个实例
n: 2500000
g: 4
v: (g*n)?100
cust: (g*n)#(n?`8)
prod: (g*n)#(n?`8)
b:([]cust:cust; prod:prod ;v:v)
q)\ts select sum v by cust, prod from b
9737 838861968
之前的查询在新数据集上运行不佳
q)\ts r:(`cust`prod xkey b inds) + select sum v by cust,prod from a til[count b] except inds:(select cust,prod from b) ? d:distinct select cust,prod from b
17181 671090384
【问题讨论】:
-
查询本身很简单,但是您可以尝试将 parted 或 group 属性应用于 cust 和/或 prod,这将使其运行得更快(以初始时间为代价)实际采取的属性)
-
谢谢,根据我的实际数据,我确实有 g# 属性,但它似乎没有帮助。可能是 g# 属性不能跨分区有效地工作?
-
这很奇怪
p和g属性应该会产生一些影响。我能想到的唯一另一件事是将表格分成更小的子集,类似于code.kx.com/wiki/Cookbook/alternateInMemLayouts -
我很难相信在公平的比较中 kdb 会慢近 10 倍,但我不知道 J 所以无法检查你的 J 代码。你确定你没有在 J 代码中预先计算一些东西吗?
-
@terrylynch - J 代码中没有预先计算任何内容。
标签: kdb