现在的位置: 首页 > 综合 > 正文

bitmap 为什么不能被delete正常使用?

2013年10月22日 ⁄ 综合 ⁄ 共 7894字 ⁄ 字号 评论关闭

同事的一个语句执行起来很慢,听说delete几乎执行不动,然后表中记录不过几万条,应该不至于啊,于是感觉上应该是语句不够优化或者是使用了不合适的索引。

首先来看看下面的查询,在没有合适索引的情况下将会有怎样的执行计划:

SQL> select count(*) from servstat where hostip in('0','127.0.0.1');

  COUNT(*)
----------
   3202637

Elapsed: 00:01:12.74

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=13654 Card=1 Bytes=1
          2)

   1    0   SORT (AGGREGATE)
   2    1     PARTITION HASH (ALL)
   3    2       TABLE ACCESS (FULL) OF 'SERVSTAT' (Cost=13654 Card=115
          950 Bytes=1391400)

Statistics
----------------------------------------------------------
        180  recursive calls
          0  db block gets
     142150  consistent gets
     141665  physical reads
          0  redo size
        494  bytes sent via SQL*Net to client
        656  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

经检查改表有一个唯一索引,可以想象,这里唯一索引显然不合时宜,看看下面的执行计划就知道了:

SQL> select /*+ index(hostip_servstat) */ hostip,count(*) from servstat group by hostip;

HOSTIP                 COUNT(*)
-------------------- ----------
0                       3102880
192.2.2.30             60366
192.2.2.31           1867308
192.2.2.32           1723927
192.2.2.33           1157024
192.2.2.34           1800699
192.2.2.35           1908348
192.2.2.36           1650781
192.2.2.37           1506685
192.2.2.38           1707074
127.0.0.1                 99757

11 rows selected.

Elapsed: 00:01:04.99

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=26 Card=11594969 Byt
          es=139139628)

   1    0   SORT (GROUP BY NOSORT) (Cost=26 Card=11594969 Bytes=139139
          628)

   2    1     INDEX (FULL SCAN) OF 'HOSTIP_SERVSTAT' (NON-UNIQUE) (Cos
          t=26 Card=11594969 Bytes=139139628)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      61968  consistent gets
      20717  physical reads
        720  redo size
        849  bytes sent via SQL*Net to client
        656  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         11  rows processed

SQL>

这列上面建立的unique索引显然不符合要求,因此drop 掉旧的索引,重建为bitmap:

SQL> drop index hostip_servstat;

Index dropped.

Elapsed: 00:00:01.28
SQL>

SQL> Create BITMAP Index hostip_servstat ON servstat(hostip) LOCAL PARALLEL 6 noLOGGING;

Index created.

Elapsed: 00:02:06.95
SQL>

再来看看执行计划:

SQL> select count(*) from servstat where hostip in('0','127.0.0.1');

  COUNT(*)
----------
   3202637

Elapsed: 00:00:04.21

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=19 Card=1 Bytes=12)
   1    0   SORT (AGGREGATE)
   2    1     SORT* (AGGREGATE)                                        :Q296600
                                                                       0

   3    2       PARTITION HASH* (ALL)                                  :Q296600
                                                                       0

   4    3         INLIST ITERATOR*                                     :Q296600
                                                                       0

   5    4           BITMAP CONVERSION* (COUNT)                         :Q296600
                                                                       0

   6    5             BITMAP INDEX* (SINGLE VALUE) OF 'HOSTIP_SERVSTAT :Q296600
          '                                                            0

   2 PARALLEL_TO_SERIAL            SELECT /*+ PIV_SSF */ SYS_OP_MSR(COUNT(*)) F
                                   ROM (SELECT /*+ NO_EXPAND INDEX_COMB

   3 PARALLEL_COMBINED_WITH_PARENT
   4 PARALLEL_COMBINED_WITH_PARENT
   5 PARALLEL_COMBINED_WITH_PARENT
   6 PARALLEL_COMBINED_WITH_PARENT

Statistics
----------------------------------------------------------
         20  recursive calls
          3  db block gets
        139  consistent gets
         11  physical reads
        856  redo size
        494  bytes sent via SQL*Net to client
        656  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          8  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

因为,bitmap是依赖于CBO的,因此如果没有analyze的情况下,delete是不会使用到该索引的,请看下面的执行计划:

SQL> delete from servstat where hostip='127.0.0.1' and rownum<2;

1 row deleted.

Elapsed: 00:01:38.62

Execution Plan
----------------------------------------------------------
   0      DELETE STATEMENT Optimizer=CHOOSE (Cost=13668 Card=1 Bytes=2
          5)

   1    0   DELETE OF 'SERVSTAT'
   2    1     COUNT (STOPKEY)
   3    2       PARTITION HASH (ALL)
   4    3         TABLE ACCESS (FULL) OF 'SERVSTAT' (Cost=13668 Card=1
          16068 Bytes=2901700)

Statistics
----------------------------------------------------------
          0  recursive calls
         13  db block gets
     396962  consistent gets
      15852  physical reads
      45528  redo size
       1021  bytes sent via SQL*Net to client
       1072  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

解决的方法有两个:

1,analyze table

2,使用 NO_EXPAND 和INDEX_COMBINE

例如:

SQL> delete /*+ NO_EXPAND INDEX_COMBINE(T HOSTIP_SERVSTAT) */ from servstat T where hostip='127.0.0.1' and rownum<2;

1 row deleted.

Elapsed: 00:00:08.16

Execution Plan
----------------------------------------------------------
   0      DELETE STATEMENT Optimizer=CHOOSE (Cost=19368 Card=1 Bytes=2
          5)

   1    0   DELETE OF 'SERVSTAT'
   2    1     COUNT (STOPKEY)
   3    2       PARTITION HASH* (ALL)                                  :Q301000
                                                                       0

   4    3         TABLE ACCESS* (BY LOCAL INDEX ROWID) OF 'SERVSTAT' ( :Q301000
          Cost=19368 Card=117976 Bytes=2949400)                        0

   5    4           BITMAP CONVERSION* (TO ROWIDS)                     :Q301000
                                                                       0

   6    5             BITMAP INDEX* (SINGLE VALUE) OF 'HOSTIP_SERVSTAT :Q301000
          '                                                            0

   3 PARALLEL_COMBINED_WITH_PARENT
   4 PARALLEL_TO_SERIAL            SELECT /*+ NO_EXPAND INDEX_COMBINE(A1 "HOSTI
                                   P_SERVSTAT") */ A1.ROWID,A1."STATID"

   5 PARALLEL_COMBINED_WITH_PARENT
   6 PARALLEL_COMBINED_WITH_PARENT

Statistics
----------------------------------------------------------
        746  recursive calls
         21  db block gets
        321  consistent gets
         41  physical reads
      10552  redo size
       1013  bytes sent via SQL*Net to client
       1127  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
         38  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

SQL> delete /*+ NO_EXPAND INDEX_COMBINE(T HOSTIP_SERVSTAT) */ from servstat T where hostip='127.0.0.1' and rownum<2;

1 row deleted.

Elapsed: 00:00:04.32

Execution Plan
----------------------------------------------------------
   0      DELETE STATEMENT Optimizer=CHOOSE (Cost=19368 Card=1 Bytes=2
          5)

   1    0   DELETE OF 'SERVSTAT'
   2    1     COUNT (STOPKEY)
   3    2       PARTITION HASH* (ALL)                                  :Q301100
                                                                       0

   4    3         TABLE ACCESS* (BY LOCAL INDEX ROWID) OF 'SERVSTAT' ( :Q301100
          Cost=19368 Card=117976 Bytes=2949400)                        0

   5    4           BITMAP CONVERSION* (TO ROWIDS)                     :Q301100
                                                                       0

   6    5             BITMAP INDEX* (SINGLE VALUE) OF 'HOSTIP_SERVSTAT :Q301100
          '                                                            0

   3 PARALLEL_COMBINED_WITH_PARENT
   4 PARALLEL_TO_SERIAL            SELECT /*+ NO_EXPAND INDEX_COMBINE(A1 "HOSTI
                                   P_SERVSTAT") */ A1.ROWID,A1."STATID"

   5 PARALLEL_COMBINED_WITH_PARENT
   6 PARALLEL_COMBINED_WITH_PARENT

Statistics
----------------------------------------------------------
          0  recursive calls
         17  db block gets
         74  consistent gets
          3  physical reads
       9728  redo size
       1017  bytes sent via SQL*Net to client
       1127  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
         10  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

抱歉!评论已关闭.