免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1864 | 回复: 1
打印 上一主题 下一主题

[Veritas NBU] (原创)Oracle's BLOOM feature 布隆过滤 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-03-15 21:44 |只看该作者 |倒序浏览
(原创)Oracle's BLOOM feature 布隆过滤










升入11.2.0.1遇到一个BLOOM过滤器导致的问题。 系统里面发生大量死锁,但是这个ORA-60伴随着另一个错误ORA-10387 ORA-00060: deadlock detected while waiting for resource ORA-10387: parallel query server interrupt (normal) 通过和ORACLE SUPPORT 沟通后,认为是由bug 9124206 和 bug 8361126引起。通过设置如下参数 NAME TYPE VALUE ------------------------------------ ----------- ------------------ _bloom_filter_enabled boolean FALSE _bloom_pruning_enabled boolean FALSE 来避免这个bug。 我在metalink想查询这两个bug,一个是no fix, 一个是not publish(杯具)。不过通过设置这个参数,我就没有看见过ORA-10387了,虽然ORA-60仍然很多(我OPEN了另外一个SR关于11g is more sensitive on deadlock) 那么什么是BLOOM 过滤呢,下面稍作解释。 BLOOM算法不是ORACLE发明的新算法,它是由Burton在1970年提出的。 BLOOM过滤是一个数据结构和算法,用于判断一个元素是否在它的集合内。 BLOOM的基本数据结构是一个数组,它的初始成员都是为0,长度为M. 【0,0,0,0,0,。。。。。。。。。。。。。。。0,0,0,0,0】 在初始化的时候,每一个要放置进去的元素,通过HASH计算出L个大小1到M的值,然后将数组的对应的成员赋值为1.一个位置,可以重复赋值。 【0,1,0,1,0,。。。。。。。。。。。。。。。0,1,0,0,1】 在进行过滤判断的时候,过程也是一样,通过HASH 算法将对应的位数算出来,然后去判断是否每一位都是1,如果是,那么就说明该元素包含在当前数据集。 但是BLOOM是存在误判的可能,这个几率和几个因素有关, 1. 数组的大小M 2. HASH函数的产生映射位数L(把几个数组成员值0置为1) 3. 以及要加入数组的元素N 为什么会产生误判?一个通俗易懂解释,就是在M数组中加入大量的元素映射后,一部分的数组元素都变成1,那么很有可能一个并不存在于数组的中的元素,在进行判断的时候,它的算出的映射位置恰好由几个其它元素的映射位置占领了,这时候就会误判它存在于这个集合。 而当M越大时,误判就会减少。 我在网上找到一段由Christian写的PL/SQL代码,可以模拟这一过程,如下: CREATE OR REPLACE PACKAGE BODY BLOOM_FILTER IS TYPE T_BITARRAY IS TABLE OF BOOLEAN; G_BITARRAY T_BITARRAY; G_M BINARY_INTEGER; G_K BINARY_INTEGER; ---------------------------------------- PROCEDURE INIT(P_M IN BINARY_INTEGER, P_N IN BINARY_INTEGER) IS BEGIN G_M := P_M; G_BITARRAY := T_BITARRAY(); G_BITARRAY.EXTEND(P_M); FOR I IN G_BITARRAY.FIRST .. G_BITARRAY.LAST LOOP G_BITARRAY(I) := FALSE; END LOOP; G_K := CEIL(P_M / P_N * LN(2)); dbms_output.put_line('G_K='||G_K); FOR I IN G_BITARRAY.FIRST .. G_BITARRAY.LAST LOOP -- dbms_output.put_line(I); IF NOT G_BITARRAY(I) THEN NULL; -- dbms_output.put_line('NO'); ELSE dbms_output.put_line('YES'); END IF; END LOOP; END INIT; ---------------------------------------- FUNCTION ADD_VALUE(P_VALUE IN VARCHAR2) RETURN BINARY_INTEGER IS A NUMBER; BEGIN DBMS_RANDOM.SEED(P_VALUE); FOR I IN 0 .. G_K LOOP A:=DBMS_RANDOM.VALUE(1, G_M); dbms_output.put_line(A); G_BITARRAY(A) := TRUE; END LOOP; RETURN 1; END ADD_VALUE; ---------------------------------------- FUNCTION CONTAIN(P_VALUE IN VARCHAR2) RETURN BINARY_INTEGER IS L_RET BINARY_INTEGER := 1; BEGIN DBMS_RANDOM.SEED(P_VALUE); -- dbms_output.put_line('G_K='||G_K); FOR I IN 0 .. G_K LOOP IF NOT G_BITARRAY(DBMS_RANDOM.VALUE(1, G_M)) THEN L_RET := 0; EXIT; END IF; END LOOP; RETURN L_RET; END CONTAIN; PROCEDURE show_nest_table IS t NUMBER:=1; BEGIN FOR I IN G_BITARRAY.FIRST .. G_BITARRAY.LAST LOOP -- dbms_output.put_line(I); IF NOT G_BITARRAY(I) THEN NULL; dbms_output.put_line(I||'IS NO'); ELSE dbms_output.put_line(I||' IS YES'); t:=t+1; END IF; END LOOP; -- END; END BLOOM_FILTER; 测试过程 创建测试表 create table t as select dbms_random.string('u',100) As VALUE from dual connect by level <=10000; BLOOM数组初始化,数组大小为15000exec bloom_filter.init(15000,1000); 加入1000个元素 (表的前1000行) select count(bloom_filter.add_value(value)) from t where rownum<=1000; 判断表中数据有多少在BLOOM数组中 select count(*) from t where bloom_filter.contain(value)=1; 实际为1000,但结果会大于1000,说明产生了误判。 通过增加数组的大小可以观察,误判逐渐消失为0.本例,大概38000的数组大小,就可以100%成功过滤1000个元素。 ORACLE在11g中支持三类类型BLOOM特性 BLOOM filter BLOOM partition pruning Support result cache 但是不幸的是,由于bug,我们已经关闭前两种。

论坛徽章:
0
2 [报告]
发表于 2012-03-15 21:44 |只看该作者
嘻嘻嘻分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP