【性能优化】8.4 [多维分析] 布尔维序列
8.4 布尔维序列
我们在前面使用对位序列提高维表过滤后的关联,这种技术还可以用于提高枚举型维度的切片性能。
所谓枚举型维度,是指维度的取值是事先已经确定的有限的几种值,如性别、产地、…;多维分析中除了时间维度外几乎全部都是枚举型维度。
这类维度的切片条件(或者更确切地说是切块)一般是给定一个维度取值集合,然后要把维度值在这个集合内的记录都过滤出来,用代码写出来相当于是:
T.select(V.contain( D) )
T 是数据表,D 是切片维度,也就是个字段,V 是用作条件的维度值列表。
contain 的计算不会很快, 在 V 不大时会使用顺序查找,在 V 较大时可以使用二分查找,也仍然要比较数次才可能确定数据是否在切片中,如果数据类型复杂,性能还会更差。
我们先将枚举维度转换成整数(一般维度取值数量不会太多,大都能转换成小于 65535 的小整数),然后在查询时将切片条件转换成布尔值构成的对位序列,在比较时就可以直接从序列指定位置取出切片判断结果,避免复杂的 contain 运算。
把维度转换成整数:
A |
|
1 |
=file("T.ctx").open() |
2 |
=file("T_new.ctx).create(…) |
3 |
=DV=A1.cursor(D).id(D) |
4 |
=A1.cursor().run(D=DV.pos@b(D)) |
5 |
=A2.append@i(A4) |
A3 要计算维度 D 所有可能的取值 DV,通常这个信息事先已经知道(比如性别、城市等),没必要去遍历表,这里为了说明它的逻辑意义而写成这样的代码。A4 利用 DV 把维度 D 转换成整数。DV 将被另外保存供查询时使用。
切片汇总代码:
A |
|
1 |
=file("T_new.ctx").open() |
2 |
=DV.(V.pos(~)) |
3 |
=A1.cursor(…;A2(D)) |
4 |
=A3.groups(…) |
A2 将参数 V 转化成一个和 DV 同长的布尔值序列,DV 的成员在 V 中时,则 A2 对应位置的成员将非空(判断时起到 true 的作用),否则填成空(也就是 false)。然后在遍历切片时,只用已经转换成整数维度 D 作为序号去取这个布尔值序列的成员,如果非空就表明原来的维度 D 是属于切片条件 V 的。序号取值的运算复杂度远远小于 contain,大幅提升切片性能。
可以对所有枚举维度做同样的处理。