3

Check-Function実行にかなり時間がかかるを使用する SQL ステートメントがあります。

の実行を並列化したいのですが、うまくいき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;
4

2 に答える 2

1
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 に通知されます。

2 番目の変更であるハッシュ パーティショニングの追加については、よくわかりません。これは、Oracle が作業負荷を分割するために使用する内部アルゴリズムに依存します。ハッシュ パーティションがある場合は、並列サーバー間でセグメントを分割するのがおそらく最も簡単です。パーティショニングを使用しない場合、少数のブロックしか存在しないため、Oracle はおそらく単一の並列サーバーですべてを実行するのが最も高速であると想定しています。

(ASSOCIATE STATISTICS関数を使用してばかげたコストを与えたとしても、Oracle はそれをシリアルに実行します。おそらく、Oracle が複数の並列サーバー間でブロックを分割しないという制限があるのでしょうか?)

これは約1.1で動作します。私のマシンで数秒。しかし、それは(AFAIK)文書化されていない動作に依存しているため、同じように動作するかどうかはわかりません. Oracle のハッシュ関数は、単純なラウンドロビン方式で値をバケットに入れません。衝突を最小限に抑え、最適な並列処理の可能性を高めるには、多数のパーティションを使用する必要があります。

@David Aldridgeが述べたように、並列クエリは実際にはこのために設計されていません。より決定論的なプロセスが必要な場合は、@Polppan によって提案されたソリューションのようなものが必要になります (DBMS_SCHEDULER を使用)。

于 2012-11-20T06:05:03.227 に答える
1

並列クエリは、この種の試行された機能用に設計されていません。

ここでの最善の行動は、関数自体の調整から始めることです。

于 2012-11-19T10:54:38.413 に答える