浅谈ORACLE的分布式事务

浅谈ORACLE的分布式事务  


平台环境:
suk: linux as4 + oracle 9201
primary: windows xp + oracle 10.2.0.3

 

首先在primary数据库上建立测试数据。
SQL> create table test as select * from dba_objects;

Table created.

SQL> insert into test select * from test;

9873 rows created.

SQL> /

19746 rows created.

SQL> /

39492 rows created.

SQL> /

78984 rows created.

SQL> /

157968 rows created.

SQL> /

315936 rows created.

SQL> commit;

Commit complete.

以下操作都是在suk数据库上执行:

一、例子1:先看两个表都在(同一个)远端
suk@ORACLE9I> select owner,count(1) fromtest@primary,dual@primary group by owner;

已选择8行。

已用时间: 00: 00: 00.87

执行计划
----------------------------------------------------------
0 SELECT STATEMENT (REMOTE) Optimizer=ALL_ROWS (Cost=1824 Card
 =670910 Bytes=11405470)

 1 0 HASH (GROUP BY) (Cost=1824 Card=670910 Bytes=11405470)
 2 1 NESTED LOOPS (Cost=1758 Card=670910 Bytes=11405470)
 3 2 FAST DUAL (Cost=2 Card=1)
 4 2 TABLE ACCESS (FULL) OF 'TEST' (TABLE) (Cost=1756 Card= PRIMARY
 670910 Bytes=11405470)


suk@ORACLE9I> select /*+ rule */ owner,count(1) fromtest@primary,dual@primary group by owner;

已选择8行。

已用时间: 00: 00: 00.89

执行计划
----------------------------------------------------------
0 SELECT STATEMENT (REMOTE) Optimizer=HINT: RULE
 1 0 SORT (GROUP BY)
 2 1 NESTED LOOPS
 3 2 FAST DUAL
 4 2 TABLE ACCESS (FULL) OF 'TEST' (TABLE) PRIMARY

以上两个例子可以说明:不管是CBO还是RBO,如果SQL中涉及的表都是远端的,那么该语句在远端执行,在得到结果后返回调用端。
这一点我们可以从执行计划的SELECT STATEMENT (REMOTE)看出。

疑问:如果例子里两个表是来自两个不同远端数据库,那么两个表的表连接操作会发生在哪里?是提交该sql语句的本地数据库【倾向于此】,还是两个不同远端数据库中的一个?

注释:SELECT STATEMENT (REMOTE)是上述一个执行计划里所有操作的根操作,即是这个执行计划发起的第一个操作,后续的操作都是由它而产生的,它是一个提纲挈领的源操作。而该源操作SELECT STATEMENT (REMOTE)里的REMOTE表示该源操作所在的执行计划是来自远端的数据库的,不是本地数据库上执行的执行计划。而像源操作SELECT STATEMENT里的没有REMOTE表示该源操作所在的执行计划就是来自本地数据库的,不是远端数据库上执行的执行计划。


二、例子2:两个包含了本地表和远端表的查询

接着再看两个包含了本地表和远端表的查询:
suk@ORACLE9I> select owner,count(1) fromtest@primary,dual group by owner;

已选择8行。

已用时间: 00: 00: 03.92

执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
 1 0 SORT (GROUP BY)
 2 1 NESTED LOOPS
 3 2 TABLE ACCESS (FULL) OF 'DUAL'
 4 2 REMOTE* PRIMARY


 4 SERIAL_FROM_REMOTE SELECT "OWNER" FROM "TEST" "TEST"

 

suk@ORACLE9I> select /*+ rule */ owner,count(1) fromtest@primary,dual group by owner;

已选择8行。

已用时间: 00: 00: 03.45

执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
 1 0 SORT (GROUP BY)
 2 1 NESTED LOOPS
 3 2 TABLE ACCESS (FULL) OF 'DUAL'
 4 2 REMOTE* PRIMARY


 4 SERIAL_FROM_REMOTE SELECT "OWNER" FROM "TEST" "TEST"


从以上两个执行结果可以看出:无论是CBO还是RBO,当查询包含了本地表和远端表时,oracle总是先把远端表的数据通过网络传送到SQL的发起端,再跟本地表进行关联得到最终结果。
从SELECT STATEMENT和SERIAL_FROM_REMOTE SELECT "OWNER" FROM "TEST" "TEST"可以看出SQL是取得远端数据后在本地执行。

疑问:如果是两个表执行union all操作,也是oracle总是先把远端表的数据通过网络传送到SQL的发起端,再跟本地表进行union all操作得到最终结果吗?


同时,要注意一个现象:如果SQL涉及的表都在远端,SQL共耗费不到1秒的时间;而如果一个表在本地,一个表在远端,返回相同的结果SQL耗费时间达到3秒多。


还要注意的是:在这种分布式事务中,看执行计划的资源消耗统计部分是没有意义的,因为本地(SQL的发起端)是不知道远端数据库的资源消耗情况。这句话是针对例子2:两个包含了本地表和远端表的查询来说的,而例子1:先看两个表都在(同一个)远端执行计划的资源消耗统计部分是有意义的,因为该执行计划就是来自远端数据库,故而自然知道远端数据库的资源消耗情况。


三、hint:driving_site对分布式查询调优的适用情况

到这里,可能很多人都会想到:如果本地表很小,远端表(准确来说是数据源)很大,且返回结果比较少的情况下,将远端表(大表)传送到本地将会引起很大的资源消耗。
很明显,要解决这样的问题,最好是把本地表数据传送到远端,然后让SQL在远端执行,得到结果后再返回到SQL发起端。
幸运的是,oracle提供一个hint来应对这种情况:driving_site

下面我们用这个hint来测试一下:
suk@ORACLE9I> select /*+ driving_site(test) */owner,count(1) fromtest@primary,dual group by owner;

已选择8行。

已用时间: 00: 00: 01.25

执行计划
----------------------------------------------------------
0 SELECT STATEMENT (REMOTE) Optimizer=ALL_ROWS (Cost=8404591 C
 ard=5479992102 Bytes=93159865734)

 1 0 HASH (GROUP BY) (Cost=8404591 Card=5479992102 Bytes=931598
 65734)

 2 1 MERGE JOIN (CARTESIAN) (Cost=7524913 Card=5479992102 Byt
 es=93159865734)

 3 2 TABLE ACCESS (FULL) OF 'TEST' (TABLE) (Cost=1756 Card= PRIMARY
 670910 Bytes=11405470)

 4 2 BUFFER (SORT) (Cost=8402834 Card=8168)
 5 4 REMOTE* OF 'DUAL' (REMOTE) (Cost=11 Card=8168) !


 5 SERIAL_FROM_REMOTE SELECT 0 FROM "SYS"."DUAL" "A1"


suk@ORACLE9I> select /*+ rule driving_site(test) */ owner,count(1) fromtest@primary,dual group by o
wner;

已选择8行。

已用时间: 00: 00: 00.71

执行计划
----------------------------------------------------------
0 SELECT STATEMENT (REMOTE) Optimizer=HINT: RULE
 1 0 SORT (GROUP BY)
 2 1 NESTED LOOPS
 3 2 REMOTE* OF 'DUAL' (REMOTE) !
 4 2 TABLE ACCESS (FULL) OF 'TEST' (TABLE) PRIMARY


 3 SERIAL_FROM_REMOTE SELECT 0 FROM "SYS"."DUAL" "A1"

注意SELECT STATEMENT (REMOTE)和SERIAL_FROM_REMOTE SELECT 0 FROM "SYS"."DUAL" "A1"与之前的测试例子的变化。

从上面两个例子可以看出:用了driving_site后,oracle将在该hint指定的数据库上执行SQL,然后在把结果返回给SQL的发起端。这个HINT对CBO和RBO都适用。



简单总结一下:
1、不管是CBO还是RBO,如果SQL中涉及的表都是远端的,那么该语句在远端执行,在得到结果后返回调用端。
2、无论是CBO还是RBO,当查询包含了本地表和远端表时,oracle总是先把远端表的数据通过网络传送到SQL的发起端,再跟本地表进行关联得到最终结果。
3、可以通过driving_site这个hint来执行SQL在那端执行。这个hints在某些特定条件下的分布式查询调优非常有用。


|      
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值