2012-11-19 82 views
3

我有一個SQL語句,它使用Check-Function這需要很長時間才能執行。並行執行SQL語句中的過程(Oracle 11g)

現在我想parallize Check-Function的執行,但它不起作用。

我犯的錯誤在哪裏?

下面的示例需要5秒才能執行,但根據我的理解,由於並行性,應該花費大約1秒。

代碼段來進行測試:

CREATE TABLE PERSON AS 
SELECT LEVEL AS ID, 'Person_'||LEVEL AS NAME 
FROM DUAL 
CONNECT BY LEVEL <= 5; 

CREATE OR REPLACE FUNCTION LONGCHECKFUNC(ID NUMBER) 
RETURN NUMBER IS 
BEGIN 
    --Doing some very heavy Checks.... 
    DBMS_LOCK.SLEEP(1 /*second*/); 
    RETURN 1; 
END; 

SELECT /*+PARALLEL(person, 5) */ * 
FROM PERSON 
WHERE LONGCHECKFUNC(ID)=1; 
+0

所以你想有一些異步執行的程序?同時並行執行多個程序? – user75ponic

+0

這是正確的。我想同時爲每個行執行相同的過程(LongCheckFunc)。 –

+1

看一看[this](http://www.oracle-base.com/articles/10g/scheduler-10g.php#simple),可能有用 – user75ponic

回答

0
CREATE TABLE PERSON 
PARTITION BY HASH(ID) PARTITIONS 16 /* <-- ADDED*/ 
AS 
SELECT LEVEL AS ID, 'Person_'||LEVEL AS NAME 
FROM DUAL 
CONNECT BY LEVEL <= 5; 

CREATE OR REPLACE FUNCTION LONGCHECKFUNC(ID NUMBER) 
RETURN NUMBER PARALLEL_ENABLE /* <-- ADDED*/ IS 
BEGIN 
    --Doing some very heavy Checks.... 
    DBMS_LOCK.SLEEP(1 /*second*/); 
    RETURN 1; 
END; 
/

SELECT /*+PARALLEL(person, 5) */ * 
FROM PERSON 
WHERE LONGCHECKFUNC(ID)=1; 

首先,您需要將PARALLEL_ENABLE添加到您的功能。這告訴Oracle,函數調用不共享任何會話數據,並且可以獨立運行。

第二個改變,加入散列分區,我不完全理解。這取決於Oracle用來劃分工作負載的內部算法。當有散列分區時,可能最容易在並行服務器中劃分這些分段。沒有分區,只有少數幾個塊,Oracle可能會認爲在單個並行服務器上運行所有內容的速度最快。

(即使使用ASSOCIATE STATISTICS並給功能的可笑成本,甲骨文將仍然運行順序。也許有一定的侷限性,其中甲骨文將永遠不會拆分多個並行服務器中的模塊?)

這將運行在約1.1。秒鐘在我的機器上。但由於它取決於(AFAIK)無證行爲,我不確定它是否會爲您運行相同。 Oracle的散列函數不會以簡單的循環方式將值存儲在存儲區中。爲了儘可能減少衝突並提高最佳並行機會,您需要使用大量的分區。

正如@David Aldridge所提到的,並行查詢並不是真正爲此設計的。如果你想要一個更確定的過程,你需要類似@Polppan建議的解決方案(使用DBMS_SCHEDULER)。

+0

非常感謝,這正是我想要的解決方案。它非常適合我! –

1

並行查詢是不適合這種嘗試的功能。

這裏最好的做法是開始調整功能本身。