当前位置: 代码迷 >> Oracle管理 >> 请问两个SQL语句不同Cost的原因
  详细解决方案

请问两个SQL语句不同Cost的原因

热度:94   发布时间:2016-04-24 04:30:23.0
请教两个SQL语句不同Cost的原因
本帖最后由 sky88088 于 2013-11-21 16:04:34 编辑
有两个效果一样的SQL语句,产生的执行计划的cost不同,我想问问为什么会有这样的差别,原理是什么?
有两个表
table_A:
name1
name2

table_B:
name,有索引table_B_idx

第一段语句
select * from table_A a
where exists (select null from table_B where a.name1=b.name or a.name2=b.name);

执行计划为
Description                            Object name                            Cost
select statement                                                                  900822
    filter                                                  
        table accesses full                 table_A                              1993
        inlist iterator
            index range scan               table_B_idx                         1



第二段语句
select * from table_A a
where a.name1 in (select name from table_B) or  a.name2 in (select name from table_B);

执行计划为
Description                            Object name                 Cost
select statement                                                        1994
    filter                                                  
        table accesses full              table_A                     1994
        index range scan               table_B_idx                 1
        index range scan               table_B_idx                 1   


事实上第二种方法确实比第一种快1/3,但是我对这两个执行计划似懂非懂,希望大牛们能指点一下这两个过程究竟区别在哪里,为什么有这么大的差别?
PS:第一次发帖,代码也没法复制,都是手敲的,哪里写得不够详细请谅解
执行计划 cost

------解决方案--------------------
一般情况下:
有两个表: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表数据大的情况。
------解决方案--------------------
上面子查询里面利用了关联子查询

关联子查询的说法:在关联子查询中,对于外部查询返回的每一行数据,内部查询都要执行一次。另外,在关联子查询中是信息流是双向的。外部查询的每行数据传递一个值给子查询,然后子查询为每一行数据执行一次并返回它的记录。然后,外部查询根据返回的记录做出决策。