本帖最后由 kay5804 于 2010-08-26 17:22:55 编辑

解决方案 »

  1.   

    SQL> select count(*) from tbl_mo_part_01 partition(MO_01) where   orgaddr='8615000000000';  COUNT(*)
    ----------
            26Elapsed: 00:00:00.01Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2243574388----------------------------------------------------------------------------------
    | Id  | Operation         | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |              |     1 |    15 |     3   (0)| 00:00:01 |
    |   1 |  SORT AGGREGATE   |              |     1 |    15 |            |          |
    |*  2 |   INDEX RANGE SCAN| MO_INX_PT_01 |    13 |   195 |     3   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------Predicate Information (identified by operation id):
    ---------------------------------------------------   2 - access("ORGADDR"='8615000000000')
           filter(TBL$OR$IDX$PART$NUM("TBL_MO_PART_01",0,1,0,ROWID)=1)
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
              3  consistent gets
              0  physical reads
              0  redo size
            530  bytes sent via SQL*Net to client
            524  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed[/code]问题:  1、 为什么两个执行计划不一样。
      2、 两个SQL执行为什么不走partition 。
      3、 为什么第一个SQL语句分区字段没有索引,会出现TABLE ACCESS BY GLOBAL INDEX ROWID
      4、 第二个SQL语句为什么指定了分区不走分区partition range 
      

  2.   

    1. 查询语句都完全不一样!
    2. part_index字段上要建索引,才会使用分区过滤!
    3. 也正迷惑中
    4. 同2
      

  3.   

    3、orgaddr上面有全局索引
      

  4.   

    1.猜测全局索引中包含了分区字段的信息,所以直接通过索引求出count(*)了。
    2.走分区未必比走索引快,你可以用大数据量少返回值的查询来验证一下执行计划是否跟现在的不同。
    3.同1
    4.事实上我自己测试的例子中走的是partition range single,然后执行的是table access full,反而没走索引,所以这个应该是跟数据和数据分布以及返回值多少有关系。
      

  5.   

    问题1:SQL1是先获取匹配的ROWID列表,然后根据ROWID列表读表中part_index的值是否为0,而SQL2则是先获取ROWID列表,然后根据ROWID直接判断该ROWID是否在指定分区中,很显然SQL2比SQL1高效,因为它不需要读表的数据
    问题2:因为索引不是局部索引。你可以暂时把索引的数据看作是一张表,你的索引表没有分区,当前不会走partition
    问题3:索引的依赖于orgaddr列,与part_index无关
    问题4:因为通过TBL$OR$IDX$PART$NUM函数可以直接判断指定的ROWID是否属于指定的分区,所以也没有partition range,原因同问题2
      

  6.   

    不同意LS所说第二种写法更高效,事实上两种的效率几乎没有差别,因为part_index=0 就可以限定在指定分区进行记录查找,执行计划没有这样走是因为有更高效的实现方式,不论数据量多少,两种写法差别不大。
      

  7.   

    part_index=0 ,因为part_index的数据不在索引中,那么如果不读表的数据,那么怎么知道它的值是0?
    从执行计划上看,它并没有如LS所说乖乖地使用限定分区的方法,没有出现partition关键字。
      

  8.   

    并不一定要有索引才能根据分区字段值来找分区,一个简单的问题,一个表有10个分区,分区字段是日期,
    那么select count(*) from tab where yyyymmdd >= 20100831; 20100831是它的一个分区,你说这个语句会走分区扫描还是全表扫描?