接上篇文章和大家持续聊一下布隆过滤器(bloom Filter)在 ORACLE 数据库中的利用。
ORACLE 数据库在以下的场景中应用到了布隆过滤器:
缩小并行联接中从过程之间的数据通信量。※1
实现连贯过滤器修剪。※2
反对后果缓存。※3
※1:available from Oracle Database 10g Release 2
※2:available from Oracle Database 11g Release 1
※3:available from Oracle Database 11g Release 1,然而因为没有具体材料,没有方法进行具体叙述。如果哪位读者有具体一点的材料,欢送补充。
对于并行联接
当两个表采纳并行执行哈希(hash)或合并联接(merge join)时,须要在有多个隶属过程之间替换数据集。例如,在以下查问的执行打算中,应用三组隶属过程(每组隶属过程领有列 TQ 中的不同标识值)。
SELECT * FROM t1, t2 WHERE t1.id = t2.id AND t1.mod = 42
-------------------------------------------------------------------------
| Id | Operation | Name | TQ |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
| 1 | PX COORDINATOR | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | Q1,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN BUFFERED | | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | Q1,02 | PCWP | |
| 5 | PX SEND HASH | :TQ10000 | Q1,00 | P->P | HASH |
| 6 | PX BLOCK ITERATOR | | Q1,00 | PCWC | |
|* 7 | TABLE ACCESS FULL| T1 | Q1,00 | PCWP | |
| 8 | PX RECEIVE | | Q1,02 | PCWP | |
| 9 | PX SEND HASH | :TQ10001 | Q1,01 | P->P | HASH |
| 10 | PX BLOCK ITERATOR | | Q1,01 | PCWC | |
| 11 | TABLE ACCESS FULL| T2 | Q1,01 | PCWP | |
-------------------------------------------------------------------------
3 - access("T1"."ID"="T2"."ID")
7 - filter("T1"."MOD"=42)
上面简略地阐明这个执行打算:
Id 5-7:
隶属过程(Q1,00)利用过滤器“7 – filter(“T1”.”MOD”=42)”扫描表 t1,而后将过滤后的数据发送到隶属过程(Q1,02)。
Id 9-11:
隶属过程(Q1,01)扫描表 t2,将数据发送到集隶属过程(Q1,02)。
Id 4,8:
隶属过程(Q1,02)接管隶属过程(Q1,00),(Q1,01)的数据。
Id 3:
隶属过程(Q1,02)把接管的数据生成哈希表。
Id 2:
隶属过程(Q1,02)把哈希表联接的行发送到主过程。
Id 0-1:
主过程接收数据并返回后果集。
下图阐明了三组从过程之间的通信。
须要留神的是,联接由隶属过程(Q1,02)执行。因而,隶属过程(Q1,00)和 隶属过程(Q1,01)发送的局部数据可能会因为不满足联接条件而被抛弃。换句话说,可能有不必要数据被发送到隶属过程(Q1,02)而造成通信开销特地显著。这种状况下,如果应用布隆过滤器在传递给隶属过程(Q1,02)之前过滤掉不满足联接条件的大多数数据,就能防止不必要的通信,从而提高效率。
上面咱们来看看上面的执行打算。
--------------------------------------------------------------------------
| Id | Operation | Name | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
| 1 | PX COORDINATOR | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | Q1,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN BUFFERED | | Q1,02 | PCWP | |
| 4 | PX JOIN FILTER CREATE| :BF0000 | Q1,02 | PCWP | |
| 5 | PX RECEIVE | | Q1,02 | PCWP | |
| 6 | PX SEND HASH | :TQ10000 | Q1,00 | P->P | HASH |
| 7 | PX BLOCK ITERATOR | | Q1,00 | PCWC | |
|* 8 | TABLE ACCESS FULL| T1 | Q1,00 | PCWP | |
| 9 | PX RECEIVE | | Q1,02 | PCWP | |
| 10 | PX SEND HASH | :TQ10001 | Q1,01 | P->P | HASH |
| 11 | PX JOIN FILTER USE | :BF0000 | Q1,01 | PCWP | |
| 12 | PX BLOCK ITERATOR | | Q1,01 | PCWC | |
| 13 | TABLE ACCESS FULL| T2 | Q1,01 | PCWP | |
--------------------------------------------------------------------------
3 - access("T1"."ID"="T2"."ID")
8 - filter("T1"."MOD"=42)
与后面的执行打算相比,多了两个附加操作(Id 4 和 11)。
•Id 4,隶属过程(Q1,02)创立了一个布隆过滤器:BF00000(如果有多个布隆过滤器,则减少数值,即第二个过滤器将命名为:BF0001)。
•Id 11,隶属过程(Q1,01)将数据发送到布隆过滤器:BF00000。用以过滤掉不满足联接条件的数据(false positives 除外)。
查问优化器(CBO)会依据预计的联接选择性和要解决的数据量决定是否应用布隆过滤器。也能够应用 Hint px_join_filter 或 no_px_join_filter 来开启或禁止布隆过滤器。然而,如果数据量较小,即便指定 px_join_filter,也无奈强制查问优化器应用布隆过滤器。若要齐全禁用此性能,能够把初始化参数_bloom_filter_enabled 设置为 FALSE。
如果要显示布隆过滤器的无关信息,能够应用动静性能视图 v$sql_join_filter。
例如,以下查问能够查看布隆过滤器筛选和探测的行数。
SQL> SELECT filtered, probed, probed-filtered AS sent
2 FROM v$sql_join_filter
3 WHERE qc_session_id = sys_context(‘userenv’,’sid’);
FILTERED PROBED SENT
———- ———- ———-
81795 100000 18205
请留神,直到 Oracle 10.2.0.3,动静性能视图 v$sql_join_filter 仅返回流动的布隆过滤器的信息。另一个动静性能视图,能够显示因为布隆过滤器缩小的通信是 v$pq_tqstat。
连贯过滤器修剪
查问优化器(CBO)可能依据 Where 条件执行分区修剪。始终到 Oracle Database 10g Release 2,当分区修剪基于联接条件时,查问优化器能够应用哈希和合并联接进行分区修剪。这种类型的修剪应用成果十分无限,因为查问的一部分被执行两次。
为了防止这种双重执行,Oracle Database 11g 提供了另一种类型的分区修剪:联接过滤器修剪(也称为布隆过滤器修剪)。上面的执行打算是一个滤器修剪的示例(Id 2 和 5)。
SELECT * FROM t1, t2 WHERE t1.id = t2.id AND t1.mod = 42
---------------------------------------------------------------
| Id | Operation | Name | Pstart| Pstop |
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | | |
|* 1 | HASH JOIN | | | |
| 2 | PART JOIN FILTER CREATE | :BF0000 | | |
| 3 | PARTITION HASH ALL | | 1 | 8 |
|* 4 | TABLE ACCESS FULL | T1 | 1 | 8 |
| 5 | PARTITION HASH JOIN-FILTER| |:BF0000|:BF0000|
| 6 | TABLE ACCESS FULL | T2 |:BF0000|:BF0000|
---------------------------------------------------------------
1 - access("T1"."ID"="T2"."ID")
4 - filter("T1"."MOD"=42)
简略的解释一下下面的执行打算。
Id 3 和 4:
扫描表 t1 的所有分区。
Id 2:
•依据 Id 3 返回的数据,创立布隆过滤器(BF0000)。
Id 5 和 6:
•布隆过滤器(BF0000),对表 t2 进行分区修剪,仅扫描蕴含相干数据的分区。
乏味的是,即便没有限度(在上一种状况下,限度为 t1.mod=42),查问优化器(CBO)也可能抉择布隆过滤器修剪。这可能是因为应用布隆过滤器修剪的开销十分小,即便不进行修剪,相干的开销也微不足道。所以如果要禁用此性能,初始化参数_bloom_pruning_enabled 必须设置为 FALSE。
论断
本文探讨了两个 ORACLE 数据库借助布隆过滤器实现的优化技术:并行联接和联接过滤器修剪。两者都致力于进步特定类型的数据量十分大的 SQL 语句的解决性能。即便不是每个人都可能利用它们,这些优化对于越来越大的数据库十分重要。心愿在将来的版本中,越来越多的这样的优化被开发进去。