布隆过滤(Bloom Filter)-必须了解的优化器算法

在最近的一次用户升级中,客户将数据库从11.2.0.1升级到了11.2.0.3版本,虽然只是一个小版本的变化,确引起了严重的性能问题。原本正常的SQL执行计划,因为使用了布隆过滤,导致了百倍的性能衰减。在版本升级中,严格的性能测试必不可少,比对SQL执行计划变化,是测试评估的必要步骤。

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

吴军博士,在《数学之美》一书中,曾经介绍过这个算法,以下内容转引自 吴军博士的文章
假定我们存储一亿个电子邮件地址,我们先建立一个十六亿二进制(比特),即两亿字节的向量,然后将这十六亿个二进制全部设置为零。对于每一个电子邮件地址 X,我们用八个不同的随机数产生器(F1,F2, ...,F8) 产生八个信息指纹(f1, f2, ..., f8)。再用一个随机数产生器 G 把这八个信息指纹映射到 1 到十六亿中的八个自然数 g1, g2, ...,g8。现在我们把这八个位置的二进制全部设置为一。当我们对这一亿个 email 地址都进行这样的处理后。一个针对这些 email 地址的布隆过滤器就建成了。(见下图)



现在,让我们看看如何用布隆过滤器来检测一个可疑的电子邮件地址 Y 是否在黑名单中。我们用相同的八个随机数产生器(F1, F2, ..., F8)对这个地址产生八个信息指纹 s1,s2,...,s8,然后将这八个指纹对应到布隆过滤器的八个二进制位,分别是 t1,t2,...,t8。如果 Y 在黑名单中,显然,t1,t2,..,t8 对应的八个二进制一定是一。这样在遇到任何在黑名单中的电子邮件地址,我们都能准确地发现。

布隆过滤能够使用极低的存储空间,存储海量数据的映射,从而可以提供快速的过滤机制。

这一算法在Oracle Database 10gR2中被引入到Oracle数据库中,在类似如下的执行计划中,就可以看到布隆过滤的作用:
-----------------------------------------------------------------------------------------------
| Id  | Operation                             | Name      | Pstart| Pstop |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |           |       |       |      |            |
|   1 |  PX COORDINATOR                       |           |       |       |      |            |
|   2 |   PX SEND QC (RANDOM)                 | :TQ10002  |       |       | P->S | QC (RAND)  |
|*  3 |    FILTER                             |           |       |       | PCWC |            |
|   4 |     HASH GROUP BY                     |           |       |       | PCWP |            |
|   5 |      PX RECEIVE                       |           |       |       | PCWP |            |
|   6 |       PX SEND HASH                    | :TQ10001  |       |       | P->P | HASH       |
|   7 |        HASH GROUP BY                  |           |       |       | PCWP |            |
|*  8 |         HASH JOIN                     |           |       |       | PCWP |            |
|   9 |          PART JOIN FILTER CREATE      | :BF0000   |       |       | PCWP |            |
|  10 |           PX RECEIVE                  |           |       |       | PCWP |            |
|  11 |            PX SEND PARTITION (KEY)    | :TQ10000  |       |       | P->P | PART (KEY) |
|  12 |             PX BLOCK ITERATOR         |           |       |       | PCWC |            |
|  13 |              TABLE ACCESS FULL        | CUSTOMERS |       |       | PCWP |            |
|  14 |          PX PARTITION HASH JOIN-FILTER|           |:BF0000|:BF0000| PCWC |            |
|* 15 |           TABLE ACCESS FULL           | SALES     |:BF0000|:BF0000| PCWP |            |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(COUNT(SYS_OP_CSR(SYS_OP_MSR(COUNT(*)),0))>100)
   8 - access("S"."CUST_ID"="C"."CUST_ID")
  15 - filter("S"."TIME_ID"<=TO_DATE(' 1999-10-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"S"."TIME_ID">=TO_DATE(' 1999-07-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
在以上执行计划中,BF0000 即 Bloom Filter的缩写提示。
而PART JOIN FILTER CREATE 这个步骤,是创建Bloom Filter的过程,在14,15 PX PARTITION HASH JOIN-FILTER中,过滤器被使用。
 在11.2.0.3中,以下一系列隐含参数和Bloom Filter相关,通过 _bloom_filter_enabled 参数可以启用或禁用布隆过滤,缺省已经启用:
NAME                   VALUE            DESCRIB
------------------------------ -------------------- ------------------------------------------------------------
_bloom_filter_enabled           TRUE            enables or disables bloom filter
_bloom_filter_debug           0            debug level for bloom filtering
_bloom_vector_elements           0            number of elements in a bloom filter vector
_bloom_predicate_enabled       TRUE            enables or disables bloom filter predicate pushdown
_bloom_predicate_pushdown_to_storage TRUE            enables or disables bloom filter predicate pushdown to storage
_bloom_folding_enabled           TRUE            Enable folding of bloom filter
_bloom_folding_density           16            bloom filter folding density lower bound
_bloom_folding_min           131072            bloom filter folding size lower bound
_bloom_pushing_max           512            bloom filter pushing size upper bound
_bloom_max_size            268435456        bloom filter maximum size in bytes
_bloom_pruning_enabled           TRUE            Enable partition pruning using bloom filtering
_bloom_pushing_total_max       262144            bloom filter combined pushing size (DOP x filter size) upperbound
_bloom_minmax_enabled           TRUE            enable or disable bloom min max filtering

Oracle的很多新特性在最初引入时,都可能带来BUG,影响性能,所以了解Oracle数据库在不同版本中引入的新特性,对于DBA来说非常重要。

以下两个链接,可以作为参考:
http://www.acoug.org/wp-content/uploads/2010/04/ACOUG-OracleSortAndBloomFilter-Fuyuncat.pdf
http://antognini.ch/papers/BloomFilters20080620.pdf
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
在Java中,你可以使用第三方库如Guava或Apache Commons等来实现布隆过滤器。下面以Guava作为示例,演示如何在Java中实现布隆过滤器: 首先,确保你已经将Guava库添加到你的项目中(通过依赖管理工具或手动添加jar文件)。 然后,按照以下步骤编写Java代码来实现布隆过滤器: 1. 导入Guava库中的布隆过滤器类: ```java import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; ``` 2. 创建布隆过滤器对象并设置参数: ```java int expectedInsertions = 1000; // 预期插入元素数量 double falsePositiveRate = 0.01; // 期望的误报率 BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), expectedInsertions, falsePositiveRate); ``` 3. 向布隆过滤器中插入元素: ```java String element = "example"; bloomFilter.put(element); ``` 4. 检查元素是否存在于布隆过滤器中: ```java boolean isPresent = bloomFilter.mightContain(element); if (isPresent) { System.out.println("Element is likely present in the Bloom Filter"); } else { System.out.println("Element is definitely not present in the Bloom Filter"); } ``` 需要注意的是,Guava库的布隆过滤器默认使用MurmurHash算法进行哈希计算。你可以根据需要调整预期插入元素数量和期望的误报率来创建适合你应用场景的布隆过滤器。 以上是使用Guava库实现布隆过滤器的简单示例。你也可以尝试使用其他第三方库或自己实现布隆过滤算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值