BITMAP索引异常增大
上一篇 / 下一篇 2008-04-19 23:00:30 / 个人分类:Bug
在一个数据库中发现了一个异常增大的对象,经检查改对象为BITMAP索引。
在数据库中执行下面的脚本,发现了一个异常增大的对象:
SQL> SELECT SEGMENT_NAME, SEGMENT_TYPE, SUM(BYTES)/1024/1024/
J[ Fho*U+_0 2 FROM USER_SEGMENTSITPUB个人空间(s!E)vR,x;o2]
3 GROUP BY SEGMENT_NAME, SEGMENT_TYPE
1vJ9L:K'B PJ|
O0 4 HAVING SUM(BYTES)/1024/1024/1024 > 15;
SEGMENT_NAME SEGMENT_TYPE G
9ILZ\9h"tZ|Vy0l0------------------------------ ------------------ ----------ITPUB个人空间Sa#O+kE eqd
TU_ORD_ORDER_ZJ_K_CODE INDEX 16.7539215
检查该对象的详细信息:
SQL> SELECT INDEX_NAME, INDEX_TYPE FROM USER_INDEXES
NSDL*T
wd*v0 2 WHERE INDEX_NAME = 'TU_ORD_ORDER_ZJ_K_CODE';
INDEX_NAME INDEX_TYPEITPUB个人空间5U ]&Y&]6DN8F$aP
------------------------------ ---------------------------
"mbC9AQ0TU_ORD_ORDER_ZJ_K_CODE FUNCTION-BASED BITMAP
这个对象是一个基于函数的BITMAP索引。一般来说,BITMAP索引的大小要远远小于普通索引,而这里索引的大小达到了
SQL> create or replace procedure p_space_usage (p_segment_name in varchar2,ITPUB个人空间"rWe9QjK2r
2 p_segment_type in varchar2 default 'TABLE',
e g)dx#AC"x@C0 3 p_segment_owner in varchar2 default user,ITPUB个人空间_JwF\:|V
4 p_partition_name in varchar2 default '') asITPUB个人空间M!c
rW#K
5 v_unformatted_blocks number;ITPUB个人空间v^O rI
6 v_unformatted_bytes number;
t$r!l L5X1Z1Z"G0 7 v_fs1_blocks number;ITPUB个人空间 c7e#q-Ef~
8 v_fs1_bytes number;ITPUB个人空间l/}M VX
9 v_fs2_blocks number;
RUU6Da#?0 10 v_fs2_bytes number;ITPUB个人空间 x4z `/U;F,\&~
11 v_fs3_blocks number;
&t$O_X*K"j3@0 12 v_fs3_bytes number;ITPUB个人空间*jN,{/j7A
13 v_fs4_blocks number;ITPUB个人空间;JD!W+xWKk
14 v_fs4_bytes number;ITPUB个人空间:@9N A qYHu?)om9J.g
15 v_full_blocks number;ITPUB个人空间g.Sv7Z6sMMo]
16 v_full_bytes number;
6~-Y4CK+c*N0 17 begin
0s7V1|yA9}T0 18 dbms_space.space_usage(upper(p_segment_owner), upper(p_segment_name), upper(p_segment_type), v_unformatted_blocks,
m2kNTC0 19 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes, v_fs3_blocks, v_fs3_bytes,
#d WO:q6u9x
{%^+AH2C5]"z0 20 v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes, upper(p_partition_name));
A(B T+AC$\&iy"@0 21
(H3X#yC%ooK0 22 dbms_output.put_line('unformatted_blocks is ' || v_unformatted_blocks);ITPUB个人空间sS[NQ-U
23 dbms_output.put_line('unformatted_bytes is ' || v_unformatted_bytes);ITPUB个人空间s1xw?'{i E}
24 dbms_output.put_line('fs1_blocks is ' || v_fs1_blocks);
A-?5H
G(A0`0 25 dbms_output.put_line('fs1_bytes is ' || v_fs1_bytes);ITPUB个人空间\m}%@] F$jRv
26 dbms_output.put_line('fs2_blocks is ' || v_fs2_blocks);
4F+GY/T5Rh!q0 27 dbms_output.put_line('fs2_bytes is ' || v_fs2_bytes);ITPUB个人空间%fq r_3}!a
AO
28 dbms_output.put_line('fs3_blocks is ' || v_fs3_blocks);
$Jf+y+z.h"N0 29 dbms_output.put_line('fs3_bytes is ' || v_fs3_bytes);
#?4C2p7C+X*m~0 30 dbms_output.put_line('fs4_blocks is ' || v_fs4_blocks);ITPUB个人空间Shd B2d:tO%SD
31 dbms_output.put_line('fs4_bytes is ' || v_fs4_bytes);
#jlb6Pa0 32 dbms_output.put_line('full_blocks is ' || v_full_blocks);
&C6tX8_S0 33 dbms_output.put_line('full_bytes is ' || v_full_bytes);ITPUB个人空间z*iJ.W,X
34 end;ITPUB个人空间3eu&G"GCdB:}
35 /
Procedure created.
SQL> SET SERVEROUT ON SIZE 10000ITPUB个人空间 @8P#VuZI#JF
SQL> EXEC P_SPACE_USAGE('TU_ORD_ORDER_ZJ_K_CODE', 'INDEX', 'NDMAIN')
+x f4VUDe J0unformatted_blocks is 2038268ITPUB个人空间;vj-t @\o:c X&R
I%{
unformatted_bytes is 16697491456ITPUB个人空间Q7VmK:o7tn/^C
fs1_blocks is 0
b;is\$F[B t^&C)n*j0fs1_bytes is 0ITPUB个人空间:f0[o!u)FbN!D
fs2_blocks is 139652ITPUB个人空间6l[!AQaj
fs2_bytes is 1144029184ITPUB个人空间IYk-k'G4DQ)k&f
fs3_blocks is 0
#O)P s O]5D#Fh0fs3_bytes is 0
HM^"NNbI[ \*Y2\0fs4_blocks is 0
j5U#H9f*j`0fs4_bytes is 0
W6WF8k6R
WneH7D0full_blocks is 13365
Ag2b|oD}7I|0full_bytes is 109486080
PL/SQL procedure successfully completed.
问题已经很显然了,这个基于函数的BITMAP索引包含了大量的unformatted blocks,造成大量空间的浪费,而实际上索引所需要的空间并没有这么大。
检查METALINK,发现Oracle处理ASSM表空间的BITMAP索引存在空间浪费的bug,详细bug描述参考:Bug No. 2915226。
Oracle给出了一个例子来重现这个bug:
SQL> SELECT TABLESPACE_NAME, SEGMENT_SPACE_MANAGEMENT ITPUB个人空间*C_
l*n)PdH
2 FROM DBA_TABLESPACES
)e:m#?IT]0 3 WHERE TABLESPACE_NAME = 'USERS';
TABLESPACE_NAME SEGMEN
+MktK,x&g0------------------------------ ------ITPUB个人空间:{0C {8La,z4F*w:MF
}
USERS AUTO
SQL> CREATE TABLE T (ID NUMBER NOT NULL, BITMAP_COL NUMBER NOT NULL);
表已创建。
SQL> INSERT INTO T SELECT ROWNUM, MOD(ROWNUM, 2) FROM DBA_OBJECTS;
已创建31016行。
SQL> CREATE BITMAP INDEX IND_B_T_BIT ON T(BITMAP_COL) TABLESPACE USERS;
索引已创建。
SQL> BEGIN
QQEe!eO-m0 2 FOR I IN REVERSE 1..1000 LOOP