DRIVING_SITE Hint (R1)

thamsyangsw發表於2014-03-20

轉載地址:http://blog.chinaunix.net/uid-20607558-id-1916125.html
在分散式查詢中,本地DB會獲取遠端表的資料進行關聯,合理使用DRIVING_SITE,可以在分散式查詢中大大減少網路流量,加快查詢速度。

 

The DRIVING_SITE hint instructs the optimizer to execute the query at a different site than that selected by the database. This hint is useful if you are using distributed query optimization.

For example:


SELECT /*+ DRIVING_SITE(departments) */ * 
  FROM employees, departments@rsite 
  WHERE employees.department_id = departments.department_id;


If this query is executed without the hint, then rows from departments are sent to the local site, and the join is executed there. With the hint, the rows from employees are sent to the remote site, and the query is executed there and the result set is returned to the local site.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
driving_site的相關說明:
 
對於那些存在遠端的SQL,ORACLE可以有兩種選擇:
1,在遠端執行SQL
2,在本地執行SQL
至於如果選擇SQL的執行地點呢,這完全是由SQL決定的,看在哪端執行的COST低就在哪端執行。但是ORACLE並不總是那麼聰明,所以有的時候需要我們自己覺得SQL在哪端執行。我們可以driving_site這個HINT來決定SQL的執行。
看下面的SQL:

SELECT /*+driving_site(a)*/
a.column_1,
b.column_2
FROM table_1@dl_remote a,
table_2 b
WHERE a.column_1 = b.column;

由於table_1是遠端的表,在/*+driving_site(a)*/提示的影響下,oracle會把表table_2傳送到dl_remote所指的遠端,
然後在遠端進行連線,最後把執行的結果在返回給本地。

SELECT /*+driving_site(b)*/
a.column_1,
b.column_2
FROM table_1@dl_remote a,
table_2 b
WHERE a.column_1 = b.column;

由於table_2是本地的表,在/*+driving_site(b)*/提示的影響下,oracle會把表table_1的資料取到本地,
然後在本地進行連線,最後把執行的結果在返回。

如果表table_1和table_2的記錄數相差很多的話,選擇合適的執行端就顯得極其重要了。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*+DRIVING_SITE(TABLE)*/

  強制與ORACLE所選擇的位置不同的表進行查詢執行.

  例如:

  SELECT /*+DRIVING_SITE(DEPT)*/ * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

出現這種執行計劃,主要原因是使用了db link,要想看到執行計劃,可以加 hint,如:
/*+remote_mapping(db_link)*/或/*+driving_site(table_name)*/


   用法:   /*+driving_site(table_name)*/  : table_name 一般是大表!

       在近期的一個資料庫查詢統計中,需要透過db_link跨庫進行表的關聯,其中A庫 中的某張擁有百萬以上資料的表與B庫 中的擁有千條記錄以上的表進行關聯。兩張表進行關聯的欄位都建有索引。但在實際查詢中如果從B庫進行兩表的關聯卻會導致A庫中大表的全表掃描,查詢速度慢是次要的,關鍵是全表掃描會影響到A庫的正常執行。

       透過對SQL語句的不斷調整、最佳化發現當兩表進行簡單的關聯查詢時,如果在select 後面採用"*"獲取所有資料時,查詢不會導致全表掃描,但在select 後面取具體欄位時將會導致大表的全表掃描。

      在簡單查詢的基礎上進行group分組將直接導致大表的全表掃描,在此種情況下,所有的語句最佳化技巧都將失效,因為索引無效,此時必須採取特殊的方法建立起關聯查詢的索引,強制指定在關聯過程中那一張表作為主要驅動表,那一張作為從表。在跨庫關聯查詢的過程中,因為表不在同一個資料庫中(同時在不同作業系統的伺服器上)將導致關聯過程中將一張表的資料提取到另一個資料庫中進行關聯。此時問題出現,如果在關聯過程中將大表資料提取到小表所在庫進行運算將導致大表的全表掃描,整個運算過程將非常慢且影響A庫的正常執行。

      最終解決全表掃描的辦法是,如果在B庫對不同資料庫的兩張大小表進行關聯時,透過driving_site強制指定主驅動表,即以所指定的表為主要表,將其它表作為從表提取到驅動表所在的庫進行關聯運算。具體語句如下:

    select /*+driving_site(main)*/  a.*,b.* from A.a minor where main.id=minor.id and .......

  這樣一來就可以避免大表所在庫的全表掃描,查詢速度將成級數級提高。

解釋:

當指定 /*+driving_site(main)*/ 時, oracle將會從minor表獲取全部資料到main表所在的資料庫來進行關聯運算.(索引起作用,速度快)
若指定 /*+driving_site(minor)*/ 時, oracle將會從main表獲取全部資料到minor表所在的資料庫來進行關聯運算.(索引失敗,全表掃描)

當然Oracle中有很多的關鍵字用於指定關聯查詢時的運算方法,等後面碰到具體應用例項實再作一一介紹。

引用:

DRIVING_SITE 作用和 ORDERED 類似。 DRIVING_SITE 通常在分散式查詢中使用。如果沒有這個提示, Oracle 會先從遠端點檢索,並將它們連線到本地站點中。透過使用 DRIVING_SITE ,我們可以先在本地進行檢索,將檢索後的資料傳送到遠端節點進行連線

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

相關文章