最近执行一个存储时,发现过程2个问题:

描述:gs_tile_p表:有一个空间索引INDEX_GS_TILE_P,数据为几千万。

        F_RACK_S表:一般索引索引有IDX_F_RACK_S_DEL(在deletetag字段上),IDX_F_RACK_S_EDITDATE(在GWM_EDITDATE段),

        IDX_F_RACK_S_FID(在GWM_FID字段),IDX_F_RACK_S_G3EFID(在G3E_FID字段);

       其空间索引为INDEX_F_RACK_S_SPATIAL。

第一个问题:

sdo_relate空间分析没有用上空间索引。

    出问题的语句:

select b.gwm_fid, b.gwm_fno, b.gwm_vno, a.gwm_tileid, b.districtid
  from gs_tile_p a, VF_RACK_S b
 where b.gwm_vno = 25700
   and b.deletetag = 0
   and b.gwm_status = 0
   and sdo_relate(a.gwm_geometry, b.gwm_geometry, 'MASK = ANYINTERACT') =
       'TRUE'
   and not exists (select 1
          from F_TILE_RACK h
         where h.gwm_fid = b.gwm_fid
           and h.TILEID >= 864691128723570689
           and h.gwm_vno = 25700)


 查看该语句的执行计划如下:

 该执行计划没有用到INDEX_GS_TILE_P索引,因此导致该语句无法查询出结果。

 不走该索引的原因分析:2011-6-17修改
 1)进行空间分析的表含有多个索引在语句中被使用,而且空间分析为多个表,容易使索引失效;可以试试使用hint(/*+ noindex(tablename,indexname)*/).

   或者直接将iDX_F_RACK_S_DEL该索引删除。

2)表数据问题:如果 筛选的条件占了视图中数据的大部分,且加了 not exists 之后,sql语句的复杂度增加了,所以oracle
 认为这个语句应该去全表扫描gs_tile_p。可以考虑使用minus替代not exists
但是这个不走索引的原因很多,比如上述语句在不同的数据库还不一样,在我自己的数据库中数据量基本是一样的,但是却可以很快查询出来,当然也用到了空间索引。

 

最近发现进行空间分析时, 使用sdo_relate空间操作符时,;

如该语句sdo_relate(a.gwm_geometry, b.gwm_geometry, 'MASK = ANYINTERACT') =  'TRUE',尽量将表数据量大的放在第一个位置,这样可以查询快很多。

 第二个问题:b树索引被转换为位图索引
 语句:
  select GWM_FID, GWM_FNO, GWM_VNO, tile_id Tileid, districtid
    from (select k.*,
                 row_number() over(partition by GWM_VNO, GWM_FID, tile_id order by tile_id) r
            from (select GWM_FID,
                         GWM_FNO,
                         GWM_VNO,
                         GWM_INCREMENT_SPATIAL.getNextLayerTileId(tileid, 11) tile_id,
                         districtid
                    from L_TILE_STREETCENTER b
                   Where deletetag = 0
                     and gwm_vno = 24849
                     and b.tileid >= 864691128723570689
                     and b.tileid <= 864692227966767104
                     and not exists
                   (select 1
                            from L_TILE_STREETCENTER d
                           where d.gwm_fid = b.gwm_fid
                             and d.gwm_vno = 24849
                             and d.tileid >= 792633534685642753
                             and d.tileid <= 792634084173023232)) k)
   where r = 1

其执行计划如下:

 

该语句始终查询不出来

而且查询计划让我感觉很奇怪,怎么会有位图索引(bitmap conversion from rowidsbitmap conversion to rowids),我根本就没有对L_TILE_STREETCENTER这个表建位图索引。

原来是系统中把B树索引转换为bitmap索引。

该转换由隐藏参数_b_tree_bitmap_plans决定。如果该参数为true,则进行转换,否则不进行转换。而8i里,该参数缺省为false; 而到了9i里,该参数缺省为true了,则对任何索引都有可能进行bitmap转换。

如果将_b_tree_bitmap_plans参数改为false

alter system set "_b_tree_bitmap_plans"=false;

Select Name ,Value From v$parameter Where Name ='_b_tree_bitmap_plans'

重新查看执行计划 发现没有转换为位图索引,sql语句也可以查询出来了。

但是仍然搞不明白,为什么会发生索引的转换呢?

发生b树索引转换为位图索引的原因:表统计信息不对,重新对表进行分析(begin dbms_stats.gather_table_stats ('GWM','L_TILE_STREETCENTER');END;),执行计划就正常了。

发生b*tree索引转为位图索引,也许执行计划也是正确的,但是仍然进行了转换,这个时候就需要测试下转换与不转换两者的性能,执行转换都需要消耗较多的CPU,因此要谨慎这种转换,如果不想修改隐含参数_b_tree_bitmap_plans的值,可以在语句中采用hint的方式(/*+ opt_param('_b_tree_bitmap_plans', 'false') */)强制不进行转换。

表分析后该sql语句的执行计划如下:

 

b树索引不再被转换为位图索引后,查询速度仍比较慢,发现与其它设施相比,该sql语句的执行计划有一个索引没有用到即IDX_L_TILE_STREETCENTERTILEDDcreate index IDX_L_TILE_STREETCENTERTILEDD on L_TILE_STREETCENTER (TILEID, GWM_FNO, DELETETAG))。为什么会没引用该索引呢?

原因分析:查询的数据占用表的数据大部分,因此CBO认为全表扫描更好。

如果改为查询tileid范围小点就可以使用索引。

引申:

查看oracle隐含参数的设置情况(sys用户查看):

select x.ksppinm name,

       y.ksppstvl value,

       y.ksppstdf isdefault,

       decode(bitand(y.ksppstvf, 7),

              1,

              'MODIFIED',

              4,

              'SYSTEM_MOD',

              'FALSE') ismod,

       decode(bitand(y.ksppstvf, 2), 2, 'TRUE', 'FALSE') isadj

 from sys.x$ksppi x, sys.x$ksppcv y

 where x.inst_id = userenv('Instance')

   and y.inst_id = userenv('Instance')

   and x.indx = y.indx

   and x.ksppinm like '%_&par%'

 order by translate(x.ksppinm, ' _', ' ')

 

posted on 2011-04-15 15:34  蓝紫  阅读(2300)  评论(0编辑  收藏  举报