T1表:RID,VID。RID:是报告ID,VID是病人流水ID,一个VID对应多个RID。R1表:是远程Oracle表,VID为主键,显示病人流水基本信息。V视图:select T.RID,T.VID,R.*  from T1 left join R1 on T1.VID=R1.VID.我们的查询是:select * from V where RID=xxx;这个搜索非常慢。若执行:select * from V where VID=xxx 则非常快。这个有没有什么方法,可以让Oracle,先查V视图中左侧T1,得出结果后,再关联远程表R1.这样就很快了。有没有类似Hint的这种,表提示,可以指定。患者

解决方案 »

  1.   

    既然是左连接,那么参与连接的时候,肯定是T1表作为驱动表,也就是你说的“先查T1表”。确认下T1表的RID字段上是否有索引?如果有,那么给一个慢查询的执行计划,嫌麻烦的话,可以先上个plsql developer F5出来的执行计划
      

  2.   

    T1表作为主表,不能加你所说的hint提示了。
    如果硬要加hint的话,也只有检查T1.VID有索引才行。最后加hint提示走T1表的索引。
      

  3.   

    这样的。T1表,RID是主键,VID是有索引的。
    R1表,VID也有索引。我查询V ,select * from V where RID
      

  4.   

    如果RID上已经有了索引,那么确认一个事情:RID是不是varchar2类型,而条件中写的是这样的:where rid=123456,而不是where rid='123456'
    如果不是这种情况,请上执行计划以作进一步的诊断~
      

  5.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。
      

  6.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。你上面说的不是VID查询没问题吗?有问题的是RID
      

  7.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。你上面说的不是VID查询没问题吗?有问题的是RID如果你其实说的那个索引是(PID,RID)的话,那么考虑下是否可以调整这个索引的字段组合顺序,当然调换后,如果你有SQL只用到了PID,而且表上没有以PID为前导字段的索引,那么PID的查询会出问题。或者,干脆直接为RID也创建一条索引。
      

  8.   

    T1表的VID,是Index(PID,VID)没说错。
    我试试单独建立一个VID索引吧。
      

  9.   


    但是你的VID查询不是没问题吗?还建VID的索引干嘛?
      

  10.   

    查询VID 是很快。
    但是查询RID时,用到的Join,是用VID链接的。我想关联键,若没有索引,可能会影响Oracle的优化策略。
    我猜,如果T1和R1的VID都有索引,可能查询where rid='xxx'时会快些。
      

  11.   


    所以我从一开始就在要求有执行计划,否则就是一直盲人摸象猜猜猜啊。从CBO一般的行为上来讲,在这种跨库查询的时候,他必然会尽力让网络上的开销变得少点,所以,没有太大意外的话,RID这个谓词必然会被推入视图内部过滤T1表,过滤完后讲数据推向远程数据库做join,看你应用,正常来说就应该是个嵌套循环,会走被驱动表,也就是远程R1表连接字段上的索引,在这个过程中,T1表上VID字段的索引是无用的,除非你创建了覆盖索引,RID、VID都建在一条索引上。另外,其实我一直怀疑你这里的T1和R1什么的是出于安全方面考虑,是加工过的,甚至SQL有些写法你可能也做过修改,我怕这修改过后的SQL,对问题的判断会有很大的误导。
      

  12.   

    还有,再多啰嗦几句,dblink这种东西,能不用就不要用,无路从性能还是其他一些方面考虑,除非你R1表和T1表连接的时候,对数据的实时性要求很高,否则建议将R1表至少使用物化视图刷至本地库,再做join,虽然你现在的应用看似并不复杂,但若是还有涉及到数据统计什么之类的应用,就可能呵呵了~
      

  13.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。Index(PID,VID)这种索引对PID,或者PID,VID组合条件生效,单独VID不生效,组合索引是对前置生效的,不过比较新版本的oracle对这块不懂有没有做处理,如果都要当作索引建议单独建两个索引吧
      

  14.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。Index(PID,VID)这种索引对PID,或者PID,VID组合条件生效,单独VID不生效,组合索引是对前置生效的,不过比较新版本的oracle对这块不懂有没有做处理,如果都要当作索引建议单独建两个索引吧
    9i之后,Oracle就支持index skip scan了,当然即使走了这种索引扫描,也不一定能得到较好的性能,其实有这种索引扫描,如果不是对DML性能要求非常非常高,或者穷的连多条索引的存储都增加不起,那么应该考虑新建一条索引。
      

  15.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。Index(PID,VID)这种索引对PID,或者PID,VID组合条件生效,单独VID不生效,组合索引是对前置生效的,不过比较新版本的oracle对这块不懂有没有做处理,如果都要当作索引建议单独建两个索引吧话说楼主已经消失了,需要的信息也缺失,看上去你提的这个问题也与楼主的烦恼无关。
    上贴已经说到,Oracle自9i起就支持index skip scan,如果他组合索引中的前导字段唯一值很少的话,那么性能对于他来说可能还是可以接受的,这不奇怪。但因为楼主一直未给出执行计划,很多东西都是在猜,不一定是他遇到的真实情况。
      

  16.   


    RID是字符串,查询也是按照where RID='xxx'。但我发现T1.VID 索引是多列。Index(PID,VID) 。这种索引可能用不到吧。Index(PID,VID)这种索引对PID,或者PID,VID组合条件生效,单独VID不生效,组合索引是对前置生效的,不过比较新版本的oracle对这块不懂有没有做处理,如果都要当作索引建议单独建两个索引吧话说楼主已经消失了,需要的信息也缺失,看上去你提的这个问题也与楼主的烦恼无关。
    上贴已经说到,Oracle自9i起就支持index skip scan,如果他组合索引中的前导字段唯一值很少的话,那么性能对于他来说可能还是可以接受的,这不奇怪。但因为楼主一直未给出执行计划,很多东西都是在猜,不一定是他遇到的真实情况。进行测试