我在这个fiddle:
中有以下几个小部分在我的数据库中,我将一次处理一个大的结果集(1亿+)记录,并需要将表示为数值的权限合并在一起。按位OR是将要使用的聚合。我的问题是,确保在小提琴中Steve
条目返回一个如下所示的元组的最有效方法是什么:
name permissions
Steve 23 --(bit_or)
我知道主要问题是跟踪我看过Steve
的时间,但我无法推断出有效的方式来处理这个问题。首选项是在数据库中完成此操作,以便materialized view
可以处理后计算结果集。
问题
使用按位聚合或听起来不吸引我。不能 你创建了一个单独的列,已经应用了该掩码?
响应
这是存储在物化视图中的内容。我得计算一下 它在某个地方。问题特别是这是一个数据仓库 不断提供数据和这些权限的应用程序 需要根据缓存策略进行相当频繁的更新 利用了。
答案 0 :(得分:3)
最有效的解决方案是可能来运行直接SQL聚合。由于权限是有限的,因此存在给定数量的个人权限(N)。您可以分解N列中的每个权限,聚合(使用MAX
)并在以下后重新组合权限:
p1 = sign(BitAnd(permissions, 2^0))
p2 = sign(BitAnd(permissions, 2^1))
...
P1 = MAX(p1)
P2 = MAX(P2)
...
Permissions = 2^0 * P1 + 2^1 * P2 + ... + 2^(N-1) * PN
但would be tedious并且您必须在添加新权限时重写查询:
SQL> select name,
2 power(2, 0) * MAX(sign(BitAnd(permissions, power(2, 0))))
3 + power(2, 1) * MAX(sign(BitAnd(permissions, power(2, 1))))
4 + power(2, 2) * MAX(sign(BitAnd(permissions, power(2, 2))))
5 + power(2, 3) * MAX(sign(BitAnd(permissions, power(2, 3))))
6 + power(2, 4) * MAX(sign(BitAnd(permissions, power(2, 4))))
7 + power(2, 5) * MAX(sign(BitAnd(permissions, power(2, 5))))
8 + power(2, 6) * MAX(sign(BitAnd(permissions, power(2, 6))))
9 + power(2, 7) * MAX(sign(BitAnd(permissions, power(2, 7))))
10 + power(2, 8) * MAX(sign(BitAnd(permissions, power(2, 8))))
11 permissions
12 from cats
13 group by name;
NAME PERMISSIONS
--------------- -----------
Carl 15
Steve 23
相反,我建议您编写自己的用户定义聚合(受此post by Tom Kyte启发 - 在9ir2上测试):
SQL> create or replace type bin_agg_type as object
2 (
3 total NUMBER,
4
5 static function
6 ODCIAggregateInitialize(sctx IN OUT bin_agg_type )
7 return number,
8
9 member function
10 ODCIAggregateIterate(self IN OUT bin_agg_type ,
11 value IN NUMBER)
12 return number,
13
14 member function
15 ODCIAggregateTerminate(self IN bin_agg_type ,
16 returnValue OUT NUMBER,
17 flags IN number)
18 return number,
19
20 member function
21 ODCIAggregateMerge(self IN OUT bin_agg_type,
22 ctx2 IN bin_agg_type)
23 return number
24 );
25 /
Type created.
SQL> create or replace type body bin_agg_type
2 is
3
4 static function ODCIAggregateInitialize(sctx IN OUT bin_agg_type )
5 return number
6 is
7 begin
8 sctx := bin_agg_type ( 0 );
9 return ODCIConst.Success;
10 end;
11
12 member function ODCIAggregateIterate(self IN OUT bin_agg_type ,
13 value IN NUMBER)
14 return number
15 is
16 begin
17 self.total := self.total + value - BitAND(self.total, value);
18 return ODCIConst.Success;
19 end;
20
21 member function ODCIAggregateTerminate(self IN bin_agg_type ,
22 returnValue OUT NUMBER,
23 flags IN number)
24 return number
25 is
26 begin
27 returnValue := total;
28 return ODCIConst.Success;
29 end;
30
31 member function ODCIAggregateMerge(self IN OUT bin_agg_type ,
32 ctx2 IN bin_agg_type )
33 return number
34 is
35 begin
36 self.total := self.total+ctx2.total - BitAND(self.total, ctx2.total);
37 return ODCIConst.Success;
38 end;
39
40
41 end;
42 /
Type body created.
SQL> CREATE or replace
2 FUNCTION BitOr_Agg(input NUMBER)
3 RETURN NUMBER
4 PARALLEL_ENABLE AGGREGATE USING bin_agg_type ;
5 /
Function created.
我们称之为:
SQL> SELECT name, bitor_agg(permissions) from cats group by name;
NAME BITOR_AGG(PERMISSIONS)
--------------- ----------------------
Carl 15
Steve 23
我很想知道哪一个是最快的。
答案 1 :(得分:0)
这是博客的Link,它在Oracle中实现了Bitwise OR聚合函数。