淺談ORACLE的分散式事務

space6212發表於2019-07-14

簡單來說,分散式事務是指涉及到多個資料庫的事務。
本文透過例子討論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資料庫上執行:

先看兩個表都在遠端的例子:
suk@ORACLE9I> select owner,count(1) from test@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) from test@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)看出。

接著再看兩個包含了本地表和遠端表的查詢:
suk@ORACLE9I> select owner,count(1) from test@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) from test@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是取得遠端資料後在本地執行。

同時,要注意一個現象:如果SQL涉及的表都在遠端,SQL共耗費不到1秒的時間;而如果一個表在本地,一個表在遠端,返回相同的結果SQL耗費時間達到3秒多。
還要注意的是:在這種分散式事務中,看執行計劃的資源消耗統計部分是沒有意義的,因為本地(SQL的發起端)是不知道遠端資料庫的資源消耗情況。

到這裡,可能很多人都會想到:如果本地表很小,遠端表(準確來說是資料來源)很大,且返回結果比較少的情況下,將遠端表(大表)傳送到本地將會引起很大的資源消耗。
很明顯,要解決這樣的問題,最好是把本地表資料傳送到遠端,然後讓SQL在遠端執行,得到結果後再返回到SQL發起端。
幸運的是,oracle提供一個hint來應對這種情況:driving_site

下面我們用這個hint來測試一下:
suk@ORACLE9I> select /*+ driving_site(test) */owner,count(1) from test@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) from test@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在某些特定條件下的分散式查詢調優非常有用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/231499/viewspace-63831/,如需轉載,請註明出處,否則將追究法律責任。

相關文章