本帖最后由 sky88088 于 2013-11-21 16:04:34 编辑

解决方案 »

  1.   

    一般情况下:
    有两个表:TABLE_A,TABLE_B
    SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B)
    in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录。IN这种情况适合TABLE_B表比TABLE_A表数据小的情况。
    SELECT * FROM TABLE_A A where exists (SELECT 1 FORM TABLE_B B WHERE B.ID = A.ID)
    exists()会执行TABLE_A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false。exists()适合TABLE_B表比TABLE_A表数据大的情况。
      

  2.   

    上面子查询里面利用了关联子查询关联子查询的说法:在关联子查询中,对于外部查询返回的每一行数据,内部查询都要执行一次。另外,在关联子查询中是信息流是双向的。外部查询的每行数据传递一个值给子查询,然后子查询为每一行数据执行一次并返回它的记录。然后,外部查询根据返回的记录做出决策。这里应该很明白了吧?相当于上面的查询要进行很多次语句执行,COST当然会要高出很多。
      

  3.   


    据我所知,在比较高版本的Oracle中,这两个语句已经优化过了,oracle会自动选择最优情况,跟代码怎么写没关系,事实上,如果只有一个字段(没有or),两种写法执行计划是一样的。而且,在我上面的两种情况里,可以看到执行计划都是对A全扫描,对B走索引,似乎不是这个原因
      

  4.   

    在两种情况下,都是要扫描一次A表,每行数据跟B表利用B表的索引匹配,这个过程好像在两种情况下没有区别啊,感觉都是A.length*1(B表走索引)。能不能说详细一点,两者的过程究竟不同在哪里?为什么第二种情况会快?
      

  5.   

    你给表A也加索引,再hint就走索引了
      

  6.   

    打个比方:你有一个过程进行大批量插入
    一个游标:
    cursor c is select * from test where id<=10000
    他插入表的时候这语句要进行多少次呢
    for i 1:9999
    Insert into test1 as select * from test where id=i
      个人见解,有点粗陋,可能理解不是很正确
      

  7.   

    你给表A也加索引,再hint就走索引了
    我在A表已经加了索引,也用/*+RULE*/试过了,是不会走索引的,谢谢!
      

  8.   

    你给表A也加索引,再hint就走索引了
    可能你们没有仔细看,我这个SQL语句不是一般的exists和in的形式比较,里面有两个字段,通过or连接起来,不是那种情况
      

  9.   

    个人觉得好像不能跟游标的情况比较。
    比如说要是用到了hash join、bitmap之类,那么确实一次读入全部数据,可以建立某种数据结构,得到与游标不一样的时间复杂度,但是看执行计划,这里好像没有这种情况。如果只是一般的全表扫描,直接读入跟游标的差别可能就是每步初始化的时间不同,时间复杂度应该是一样的吧?但是从执行计划看来,cost差那么远,感觉是时间复杂度不同。
    不知道我的理解对否?
      

  10.   

    你给表A也加索引,再hint就走索引了
    我在A表已经加了索引,也用/*+RULE*/试过了,是不会走索引的,谢谢!
    这样 select /*+index(a 索引名)*/* from 表A a
      

  11.   

    你给表A也加索引,再hint就走索引了
    我在A表已经加了索引,也用/*+RULE*/试过了,是不会走索引的,谢谢!
    这样 select /*+index(a 索引名)*/* from 表A a
    ……
    我是想要知道上面这两种写法本质上有什么区别,就算从业务来说,也是想要效率更高,那么执着于走一个没必要走的索引干什么……
    by the way:那样还是不会走索引的,那是两个字段
      

  12.   

    我是想说明比如select * from test where id=1
    union all
    select * from test where id=2
    union all'''''''''''''''''.........................
    select * from test where id=10000
    和   select * from test where id>=1 and id<=10000 这个COST 是一样的吗?
      

  13.   

    嗯,隐约好像是这个意思
    就是第一种情况是全扫描A表,每一行去跑一次B表的索引;第二次情况是全扫描A表,整体去跑B表的索引,略懂了