oracle在大结果集上的逐位计算

时间:2012-11-13 16:14:17

标签: sql oracle plsql

我在这个fiddle

中有以下几个小部分

在我的数据库中,我将一次处理一个大的结果集(1亿+)记录,并需要将表示为数值的权限合并在一起。按位OR是将要使用的聚合。我的问题是,确保在小提琴中Steve条目返回一个如下所示的元组的最有效方法是什么:

name     permissions   
Steve    23 --(bit_or)  

我知道主要问题是跟踪我看过Steve的时间,但我无法推断出有效的方式来处理这个问题。首选项是在数据库中完成此操作,以便materialized view可以处理后计算结果集。

问题

  

使用按位聚合或听起来不吸引我。不能   你创建了一个单独的列,已经应用了该掩码?

响应

  

这是存储在物化视图中的内容。我得计算一下   它在某个地方。问题特别是这是一个数据仓库   不断提供数据和这些权限的应用程序   需要根据缓存策略进行相当频繁的更新   利用了。

2 个答案:

答案 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聚合函数。