ITPub博客

首页 > Linux操作系统 > Linux操作系统 > BITMAP索引异常增大

BITMAP索引异常增大

原创 Linux操作系统 作者:yangtingkun 时间:2008-04-19 23:00:30 0 删除 编辑

在一个数据库中发现了一个异常增大的对象,经检查改对象为BITMAP索引。

 

 

在数据库中执行下面的脚本,发现了一个异常增大的对象:

SQL> SELECT SEGMENT_NAME, SEGMENT_TYPE, SUM(BYTES)/1024/1024/1024 G
  2  FROM USER_SEGMENTS
  3  GROUP BY SEGMENT_NAME, SEGMENT_TYPE
  4  HAVING SUM(BYTES)/1024/1024/1024 > 15;

SEGMENT_NAME                   SEGMENT_TYPE                G
------------------------------ ------------------ ----------
TU_ORD_ORDER_ZJ_K_CODE         INDEX              16.7539215

检查该对象的详细信息:

SQL> SELECT INDEX_NAME, INDEX_TYPE FROM USER_INDEXES     
  2  WHERE INDEX_NAME = 'TU_ORD_ORDER_ZJ_K_CODE';

INDEX_NAME                     INDEX_TYPE
------------------------------ ---------------------------
TU_ORD_ORDER_ZJ_K_CODE         FUNCTION-BASED BITMAP

这个对象是一个基于函数的BITMAP索引。一般来说,BITMAP索引的大小要远远小于普通索引,而这里索引的大小达到了16G,远远超过表本身的大小,这里肯定存在问题。通过对DBMS_SPACE包中SPACE_USAGE过程的封装,检查这个对象的空间使用情况:

SQL> create or replace procedure p_space_usage (p_segment_name in varchar2,
  2     p_segment_type in varchar2 default 'TABLE',
  3     p_segment_owner in varchar2 default user,
  4     p_partition_name in varchar2 default '') as
  5     v_unformatted_blocks number;
  6     v_unformatted_bytes number;
  7     v_fs1_blocks number;
  8     v_fs1_bytes number;
  9     v_fs2_blocks number;
 10     v_fs2_bytes number;
 11     v_fs3_blocks number;
 12     v_fs3_bytes number;
 13     v_fs4_blocks number;
 14     v_fs4_bytes number;
 15     v_full_blocks number;
 16     v_full_bytes number;
 17  begin
 18     dbms_space.space_usage(upper(p_segment_owner), upper(p_segment_name), upper(p_segment_type), v_unformatted_blocks,
 19             v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes, v_fs3_blocks, v_fs3_bytes,
 20             v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes, upper(p_partition_name));
 21    
 22     dbms_output.put_line('unformatted_blocks is ' || v_unformatted_blocks);
 23     dbms_output.put_line('unformatted_bytes is ' || v_unformatted_bytes);
 24     dbms_output.put_line('fs1_blocks is ' || v_fs1_blocks);
 25     dbms_output.put_line('fs1_bytes is ' || v_fs1_bytes);
 26     dbms_output.put_line('fs2_blocks is ' || v_fs2_blocks);
 27     dbms_output.put_line('fs2_bytes is ' || v_fs2_bytes);
 28     dbms_output.put_line('fs3_blocks is ' || v_fs3_blocks);
 29     dbms_output.put_line('fs3_bytes is ' || v_fs3_bytes);
 30     dbms_output.put_line('fs4_blocks is ' || v_fs4_blocks);
 31     dbms_output.put_line('fs4_bytes is ' || v_fs4_bytes);
 32     dbms_output.put_line('full_blocks is ' || v_full_blocks);
 33     dbms_output.put_line('full_bytes is ' || v_full_bytes);
 34  end;
 35  /

Procedure created.

SQL> SET SERVEROUT ON SIZE 10000
SQL> EXEC P_SPACE_USAGE('TU_ORD_ORDER_ZJ_K_CODE', 'INDEX', 'NDMAIN')
unformatted_blocks is 2038268
unformatted_bytes is 16697491456
fs1_blocks is 0
fs1_bytes is 0
fs2_blocks is 139652
fs2_bytes is 1144029184
fs3_blocks is 0
fs3_bytes is 0
fs4_blocks is 0
fs4_bytes is 0
full_blocks is 13365
full_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         
  2  FROM DBA_TABLESPACES
  3  WHERE TABLESPACE_NAME = 'USERS';

TABLESPACE_NAME                SEGMEN
------------------------------ ------
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
  2  FOR I IN REVERSE 1..1000 LOOP
  3  UPDATE T SET BITMAP_COL = 1
  4  WHERE BITMAP_COL = 0  AND ID = I;
  5  END LOOP;
  6  END;
  7  /

PL/SQL 过程已成功完成。

SQL> SET SERVEROUT ON SIZE 1000000
SQL> EXEC P_SPACE_USAGE('IND_B_T_BIT', 'INDEX')
unformatted_blocks is 93536
unformatted_bytes is 766246912
fs1_blocks is 0
fs1_bytes is 0
fs2_blocks is 8211
fs2_bytes is 67264512
fs3_blocks is 0
fs3_bytes is 0
fs4_blocks is 0
fs4_bytes is 0
full_blocks is 18
full_bytes is 147456

PL/SQL 过程已成功完成。

这个结果和这里碰到的问题几乎完全一致,只不过这个例子是人为构造bug的产生,而数据库中则是由于正常修改在某些情况下触发了这个bug,检查当前的表空间信息:

SQL> SELECT INDEX_NAME, TABLESPACE_NAME FROM USER_INDEXES 
  2  WHERE INDEX_NAME = 'TU_ORD_ORDER_ZJ_K_CODE';

INDEX_NAME                     TABLESPACE_NAME
------------------------------ ------------------------------
TU_ORD_ORDER_ZJ_K_CODE         INDX

SQL> SELECT SEGMENT_SPACE_MANAGEMENT FROM USER_TABLESPACES  
  2  WHERE TABLESPACE_NAME = 'INDX';

SEGMEN
------
AUTO

这个Bug在10.1.0.2被修正,对于9.2.0.2以上的版本,可以直接下载编号为2915226的patch来解决这个问题。

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-244198/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: ORA-26500错误
请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1964
  • 访问量
    11077115