在一个分区表上去执行一个SQL时(在Where条件中用了分区列等于的条件, 分区列为主键索引的最后一列), 发现用错了执行计划, Oracle居然认为某个SQL的执行计划的成本为0, 实际上是肯定没有本为0的执行计划的, 因此是明显的不合理的现象.

SQLPLAN                                          COST CARD KBYTE PS PE
------------------------------------------------ ---- ---- ----- -- --
  0     SELECT STATEMENT Optimizer=RULE             0    1     0
  1   0   SORT (GROUP BY)                                1     0
  2   1     PARTITION RANGE (SINGLE)                0    1     0 3  3
  3   2       TABLE ACCESS (BY LOCAL INDEX ROWID    0    1     0 3  3
  4   3         INDEX (SKIP SCAN) OF TEST_TAB_PK    0    1       3  3

    产生的原因是因为分区的统计信息是过时的, 执行分析时这个分区还没有任何记录, 就产生了这个问题.

ASQL> SELECT PARTITION_NAME, BLEVEL,LEAF_BLOCKS,
    2        DISTINCT_KEYS,NUM_ROWS
    3 FROM DBA_IND_PARTITIONS
    4 WHERE INDEX_NAME='TEST_TAB_PK';

PARTITION_NAME   BLEVEL LEAF_BLOCKS DISTINCT_KEYS NUM_ROWS
---------------- ------ ----------- ------------- --------
TEST_TAB_PK_P06       0           0             0        0
TEST_TAB_PK_P07       3      364320      73835520 73835520
TEST_TAB_PK_P08       0           0             0        0
TEST_TAB_PK_P09       0           0             0        0
TEST_TAB_PK_P10       0           0             0        0
TEST_TAB_PK_PMAX      0           0             0        0

    但很显然Oracle这样算是不合理的, 谁能天天去分析表呢, 又有谁敢呢? 最好是当统计值为0时, 当作默认值来处理, 在另一个没有分析过的数据库上就是好的. 现在最好的做法, 就是分析后, 将空的分区上的统计信息删除, 当然可以用程序来做到这一点.

    在7x24小时的OLTP系统中, 分区是要用的, 出了问题是严重的, 你有什么高见?