oracle driving_site特点简析

一.准备工作:
先要创建一个数据库:orcl_ysy,然后解锁账户,创建dblink

alter user scott identified by tiger;
alter user scott account unlock ;

--授予orcl 下的yushaoyang001 dblink 权限
grant create public database link to yushaoyang001;
grant drop public database link to yushaoyang001;

select * from user_sys_privs where privilege like upper('%DATABASE LINK%') ;


--如果密码是数字开头,用“”括起来
--创建DBLINK
create public database link scottlink connect to scott identified by "tiger" USING 'ORCL_YSY';
--查看dblink
select * from all_db_links;
drop public database link scottlink;

--在orcl_ysy下创建一个
create table oracl_sys_temp
as
select * from all_objects;
--insert为一个大表
insert into oracl_sys_temp
select * from oracl_sys_temp
-- 3560384
select count(1) from oracl_sys_temp;


--在yushaoyang001访问
select * from oracl_sys_temp@scottlink;
会发现产生事务了,此时需要commit或者rollback;
这种分布式事务是为了保持数据的一致性;
规律:
当需要的数据都返回了,就不会产生要commit提示,否则就会产生commit提示。
如: select count(1) from oracl_sys_temp@scottlink;不会出现;
具体参考:
https://docs.oracle.com/cd/B28359_01/server.111/b28310/ds_txnman.htm#i1207516


二,开始说明
driving_site这个hint比较特别针对RBO也可以生效的;
driving_site(xx):指定在表xx所在的节点执行;此时xx所在的节点就相当于’本地’了;以此作为参照,另外的表就可看做’远程’;
这里有2个库:一个orcl的,账户为yushaoyang001,一个库为orcl_ysy,账户为scott,上面创建的dblink就是这个scott账户

--在yushaoyang001账户下创建表
create table tab1_temp
as
select * from all_objects where  rownum<50;

explain plan for 
select tt.* from tab1_temp tt,oracl_sys_temp@scottlink os
where tt.object_id=os.object_id;
select * from table(dbms_xplan.display(null,null,'advanced'));

这里写图片描述
这里写图片描述

等价于:
select /*+ driving_site(tt) */tt.* from tab1_temp tt,oracl_sys_temp@scottlink os
where tt.object_id=os.object_id;
可以看到CBO选择了在本地节点tt执行,即将远程数据os传输到本地,再走hash操作;
此时oracl_sys_temp 有3560384记录,执行时间为4.585s左右;
此时主要是网络传输的消耗;


--现在强制走远程节点,即把tab1_temp数据传输到oracl_sys_temp@scottlink所在节点执行,再返回结果;
select /*+ driving_site(os) */tt.*,os.object_name from tab1_temp tt,oracl_sys_temp@scottlink os
where tt.object_id=os.object_id;

这里写图片描述
这里写图片描述
1.发现执行计划的remote 对应的表为tab1_temp,说明把tab1_temp所在的节点当成了远程环境,此时把tab1_temp数据传输到oracl_sys_temp@scottlink所在节点执行,再返回结果到tab1_temp所在的节点;
2.Remote SQL Information
也可以知道此时远程执行的是tab1_temp;
以及从备注可以看到全部远程执行再返回;
执行时间:0.068左右;
虽然涉及到了2次网络返回;
如果本地表小,且返回的数据也小的话,强制走远程节点访问肯定是效率最好的;

再看一个问题: driving_site 能不能跟其他hint一起用?
–情况1 在本地节点
explain plan for
select /+ driving_site(tt) use_nl(tt,os) /tt.*,os.object_name from tab1_temp tt,oracl_sys_temp@scottlink os
where tt.object_id=os.object_id;
select * from table(dbms_xplan.display(null,null,’advanced’));
这里写图片描述
这里写图片描述
可以发现hint已经生效,
但是仔细看,虽然use_nl(tt,os)指定了os作为被驱动表,但是实际来看没有生效;于是要使用leading强制了

–情况2 指定在远程节点
explain plan for
select /+ driving_site(os) use_nl(tt,os) leading(tt) /tt.*,os.object_name from tab1_temp tt,oracl_sys_temp@scottlink os
where tt.object_id=os.object_id;
select * from table(dbms_xplan.display(null,null,’advanced’));

这里写图片描述
这里写图片描述
此时hint确实生效了;
说明了: driving_site可以跟use_nl及leading一起使用;

后话:在远程表oracl_sys_temp加一个索引,走NL更快;

小结:
1.通过remote对应的表和Remote SQL Information以及注释三个方面都可以判断sql是在本地还是远程执行,默认在本地节点执行;
2.如果本地表小,且返回的数据也小的话,强制走远程节点访问效率最好的;
3. driving_site可以跟use_nl及leading一起使用;

猜你喜欢

转载自blog.csdn.net/u011165335/article/details/81609344