0

我有以下场景在这个小提琴中很简单:

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

name     permissions   
Steve    23 --(bit_or)  

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

问题

使用按位聚合或听起来对我没有吸引力。您不能创建一个已应用该掩码的单独列吗?

回复

这就是存储在物化视图中的内容。我必须在某个地方计算它。问题特别是,这是一个数据仓库应用程序,它不断地被提供数据,并且这些权限需要根据所使用的缓存策略相当频繁地更新。

4

2 回答 2

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

但这会很乏味,并且在添加新权限时必须重写查询:

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

相反,我建议您编写自己的用户定义聚合(受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

我很想知道哪个是最快的。

于 2012-11-13T16:37:58.710 回答
0

这是一个博客链接,该博客在 Oracle 中实现了按位或聚合函数。

于 2012-11-13T16:35:21.210 回答