Bitmap 索引 vs. Btree 索引:如何选择以及何时使用?——45

——理解适当使用每个索引对性能的影响

Bitmap 索引 vs. B-tree 索引:如何选择以及何时使用?——1-5

Bitmap 索引 vs. B-tree 索引:如何选择以及何时使用?——2-5

Bitmap 索引 vs. B-tree 索引:如何选择以及何时使用?——3-5

Bitmap 索引 vs. B-tree 索引:如何选择以及何时使用?——4-5

Bitmap 索引 vs. B-tree 索引:如何选择以及何时使用?——5-5

本文内容

  • 步骤 6(添加一个 GENDER 列)

步骤 6(添加一个 GENDER 列)


在一个低基数列执行测试前,向表添加一个 GENDER 列,并基于某个条件用 M、F、null 值来更新。

SQL> alter table test_normal add GENDER varchar2(1);
 
表已更改。
 
SQL>

用下面匿名过程更新 GENDER 列的值,之后看看列值如何分布:

DECLARE
  v_empno test_normal.empno%type;
  CURSOR c IS
    SELECT empno FROM test_normal;
BEGIN
  OPEN c;
  LOOP
    FETCH c
      INTO v_empno;
    exit when c%notfound;
    IF dbms_random.random MOD 3 = 1 THEN
      UPDATE test_normal set gender = 'M' WHERE empno = v_empno;
    ELSIF dbms_random.random mod 3 = 2 THEN
      UPDATE test_normal set gender = 'F' WHERE empno = v_empno;
    ELSIF dbms_random.random mod 3 = 0 THEN
      UPDATE test_normal set gender = null WHERE empno = v_empno;
    END IF;
    commit;
  END LOOP;
  CLOSE c;
END;
SQL> select GENDER, count(*) from test_normal group by GENDER;
 
GENDER       COUNT(*)
---------- ----------
               385961
M              320767
F              293272
 
SQL>

该列上的 Bitmap 索引大小约在 620KB 左右,如下所示:

SQL> create bitmap index normal_GENDER_bmx on test_normal(GENDER);
 
索引已创建。
 
SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
  2  from user_segments
  3  where segment_name in ('TEST_NORMAL','NORMAL_GENDER_BMX');
 
SEGMENT_NAME                                                 Size in MB
------------------------------------------------------------ ----------
NORMAL_GENDER_BMX                                                  .625
TEST_NORMAL                                                          50
 
SQL>

相比,该列上的 B-tree 索引为 9MB,比 Bitmap 索引大很多。

SQL> drop index normal_gender_bmx;
 
索引已删除。
 
SQL> create index normal_gender_idx on test_normal(gender);
 
索引已创建。
 
SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
 
  2  from user_segments
  3  where segment_name in ('TEST_NORMAL','NORMAL_GENDER_IDX');
 
SEGMENT_NAME                                                 Size in MB
------------------------------------------------------------ ----------
NORMAL_GENDER_IDX                                                     9
TEST_NORMAL                                                          50
 
SQL>

现在,若执行一个等值谓词查询,那么优化器将不使用索引,Bitmap 索引或 B-tree 索引。而是执行一个全表扫描。

SQL> select * from test_normal where GENDER is null;
 
已选择385961行。
 
 
执行计划
----------------------------------------------------------
Plan hash value: 512490529
 
---------------------------------------------------------------------------------
| Id  | Operation         | Name        | Rows  | Bytes | Cost (%CPU)| Time|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |             |  1000K|    37M|  1725   (2)| 00:00:21|
|*  1 |  TABLE ACCESS FULL| TEST_NORMAL |  1000K|    37M|  1725   (2)| 00:00:21|
---------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("GENDER" IS NULL)
 
 
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      31825  consistent gets
          0  physical reads
          0  redo size
   22065645  bytes sent via SQL*Net to client
     283550  bytes received via SQL*Net from client
      25732  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     385961  rows processed
 
SQL>
SQL> select * from test_normal where GENDER='M';
 
已选择320767行。
 
 
执行计划
----------------------------------------------------------
Plan hash value: 654360527
 
-------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                   |     1 |    39 |     2  (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST_NORMAL       |     1 |    39 |     2  (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | NORMAL_GENDER_IDX |     1 |       |     2  (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("GENDER"='M')
 
 
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      49138  consistent gets
          0  physical reads
          0  redo size
   19044637  bytes sent via SQL*Net to client
     235744  bytes received via SQL*Net from client
      21386  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     320767  rows processed
 
SQL>
SQL> select * from test_normal where GENDER='F';
 
已选择293272行。
 
 
执行计划
----------------------------------------------------------
Plan hash value: 654360527
 
-------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                   |     1 |    39 |     2  (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST_NORMAL       |     1 |    39 |     2  (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | NORMAL_GENDER_IDX |     1 |       |     2  (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("GENDER"='F')
 
 
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      45430  consistent gets
          0  physical reads
          0  redo size
   17412131  bytes sent via SQL*Net to client
     215581  bytes received via SQL*Net from client
      19553  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     293272  rows processed
 
SQL>

表 8 Bitmap 索引在 TEST_NORMAL 表 EMPNO、SAL 和 GENDER 列的统计信息 

  EMPNO SAL GENDER
基数程度   高   一般   低
size   28MB   4MB   625KB

基数越低,Bitmap 索引越小。

表 9 B-tree 索引在 TEST_NORMAL 表 EMPNO、SAL 和 GENDER 列的统计信息

  EMPNO SAL GENDER
基数程度   高   一般   低
size   18MB   17MB   9MB
原文地址:https://www.cnblogs.com/liuning8023/p/2765426.html