6.2.2各类连接访问次数的差异 6.2.2.1嵌套循环的表访问次数 drop table t1 cascade constraints purge; drop table t2 cascade constraints purge; create table t1 ( id number not null, n number, contents varchar2(4000) );
create table t2 ( id number not null, n number, contents varchar2(4000) );
execute dbms_random.seed(0); insert into t1 select rownum, rownum, dbms_random.string('a',50) from dual connect by level<=100 order by dbms_random.random; insert into t2 select rownum, rownum, dbms_random.string('b',50) from dual connect by level<=100000 order by dbms_random.random;
commit;
select count(*) from t1; select count(*) from t2;
1.T2表为哈被访问100次? 测试表连接语法: select /*+leading(t1) use_nl(t2)*/ * from t1,t2 where t1.id=t2.t1_id;
表访问次数跟踪语法: alter session set statistics_level=all;
set linesize 1000 select /*+leading(t1) use_nl(t2)*/ * from t1,t2 where t1.id=t2.t1_id;
查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); 其中 starts列表示表访问的次数,T1表1次,T2表100次。
2.100次又变成2次 为t1增加一个条件: select /*+leading(t1) use_nl(t2) */ * from t1,t2 where t1.id=t2.t1_id and t1.n in (17,19); 查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); 其中 T1表访问1次,T2表访问2次。
3.2次又变成1次 select /*+leading(t1) use_nl(t2) */ * from t1,t2 where t1.id=t2.t1_id and t1.n=19;
查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
其中T1表访问1次,T2表访问1次
4.1次又变成0次
select /*+leading(t1) use_nl(t2) */ * from t1,t2 where t1.id=t2.t1_id and t1.n=999999; 查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
其中T1表访问1次,T2表访问0次
5.嵌套循环连接结论 我们在t1表中只有100个数据。 第一次查询全部100个数据,要返回100,读t2表100次。 第四次查询t1表没有符合项,不访问t2表。
6.2.2.2哈希连接的表访问次数
1.测试t2表仅访问1次
测试脚本: select /*+leading(t1) use_hash(t2)*/ * from t1,t2 where t1.id=t2.t1_id;
查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
2.HASH连接结论
T1表返回10条记录,T2表返回1次,,说明哈希连接中被驱动表的访问次数和驱动表的返回记录无关。驱动表T1和被驱动表T2都只会访问1次。 也就是说,在HASH连接中,驱动表和被驱动表都只会访问0次,或者1次。
select /*+leading(t1) use_hash(t2)*/ * from t1 ,t2 where t1.id=t2.t1_id and t1.n=99999999;
查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); 结果表明: 哈希连接中T2被访问了0次;
查看t1表访问0次的情况: (1=2表示语句一定不成立,所以返回0) select /*+leading(t1) use_hash(t2)*/ * from t1 ,t2 where t1.id=t2.t1_id and t1.n=99999999; 查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); 结果表明: T1,T2都只被访问0次
6.2.2.3排序合并的表访问次数 测试语句: select /*+leading(t1) use_merge(t2)*/ * from t1 ,t2 where t1.id=t2.t1_id and t1.id=t2.t1_id; 查看执行计划: select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
结论: 排序合并连接和Hash连接一样,T1和T2表都只会访问0次或1次。 排序合并连接并没有驱动与被驱动的概念。
|