• 不走空间索引及B树索引转换为bitmap索引问题解决


         最近执行一个存储时,发现过程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, ' _', ' ')

     

  • 相关阅读:
    Linux 查看CPU信息,机器型号,内存等信息
    TCPdump抓包命令详解
    nginx https 转发
    滚动效果
    phpexcel中文手册(转)
    Java数组操作十大方法 (转)
    ajax防止重复提交
    信用评分卡(A卡/B卡/C卡)的模型简介及开发流程|干货
    求方差分析与两样本T检验 区别
    互联网运营中的10大数据分析方法
  • 原文地址:https://www.cnblogs.com/lanzi/p/2017234.html
Copyright © 2020-2023  润新知