我有一个A表和一个B表,它们结构是一样的。现在要用B表更新A表。因为A表中有大量数据,所以在它上面建立了两个索引idx1和idx2,分别对应col1和col2两列。merge into A a
using B b
on (a.col1=b.col1 and a.col2=b.col2)
when matched then update ...以上就是我写的类似的更新语句,运行会非常慢。通过Explain Plan,发现只用了idx2这个索引,而idx1根本就没用上。不管我把关联条件的顺序如何调换,都是一样的。因为通过idx2这个索引查询出来的数据量还是很庞大的,所以运行会及其慢。最后我把idx2索引删除掉,这样它才会去使用idx1索引。通过idx1索引查询的数据量是很小的,所以会很快运行完。难道oracle在做merge时是缺省使用某一个索引么,用户不能干预的?我知道在select时用户可以通过/*+index*/ hint去指定,不知道在merge时能否这样

解决方案 »

  1.   

    可以同时使用多个索引(但效率不一定高,如果基于COST的优化模式,在统计数据正常有效的情况下,最好由系统自已决定,除非极端情况下,执行计划不正确)。如:使用and_equal的hint:
    如:merge /*+and_equal(a,idx1,idx2)*/ into A a using B b......
      

  2.   

    试试index_join
    merge /*+index_join(a idx idx2)*/into A a...
      

  3.   

    and_equal:
    这种方式需要查询条件里面包括所有索引列,然后取得每个索引中得到的rowid列表,然后对这些列表做merge join,过滤出相同的rowid后再去表中获取数据或者直接从索引中获得数据.and_equal有一些限制,比如它只对单列索引有效,只对非唯一索引有效,使用到的索引不能超过5个,查询条件只能是”=”.在10g中,and_equal已经被废弃了,只能通过hint才能生效.index_join:
    index join顾名思义是对index进行关联,oracle通过hash index join的方式实现了避免对表的访问.所有的数据都从索引中直接获得.它不受查询条件影响,可以是唯一索引,也可以是多列索引.index combine最早是用在bitmap index上的,在9i开始oracle默认可以使用在btree索引上,这是由_b_tree_bitmap_plans参数来控制的.oracle将 btree索引中获得的rowid信息通过BITMAP CONVERSION FROM ROWIDS的步骤转换成bitmap进行匹配,然后匹配完成后通过BITMAP CONVERSION TO ROWIDS再转换出rowid获得数据或者回表获得数据.