手順に問題があります。「大きな」セット (800 以上の親、1300 以上の子) に対して実行すると、非常に遅くなります (30 ~ 60 秒)。
基本的な考え方は、特定の検索基準に適合するすべての親レコード (およびそれぞれの子レコード) と、計算する必要がある 3 つの追加情報を取得することです。
問題に対する私のアプローチは
- 計算値用の追加フィールドを持つカスタム レコード タイプを作成します。
- このレコード タイプへの参照は、メイン処理関数によって制御される各関数に渡すことができます。
- 親レコードごとに値が計算されるので、それをレコードに追加します。
各プロシージャGET_PARENT_RECORDS
とGET_CHILD_RECORDS
は検索ごとに 1 回呼び出され、各計算関数は N 回実行されます (N は親レコードまたは子レコードの数です)。
質問 1 : これは正しいアプローチですか? (弱く型付けされたカーソル、パイプライン化された関数) そうでない場合、やり直すことができると仮定して、どのように問題に取り組むべきでしたか?
質問 2 : 完全な書き直しを除いて、提供されたコードで明らかに改善できる点はありますか?
質問 3 : または、プロシージャを数回実行したときに、同じ遅いクエリが 20 秒で返されたことに気付いたので、何か他のことが間違っている可能性がありますか?
パッケージ定義
create or replace
PACKAGE THIS_PKG AS
Type parentCursor IS REF CURSOR;
Type childCursor IS REF CURSOR;
Type ParentRecordType IS RECORD (
other_columns,
Extra_column_A,
Extra_column_B,
Extra_column_C,
Row_num);
--associative array
TYPE ParentArray IS TABLE OF ParentRecordType;
FUNCTION processParents(
p IN THIS_PKG. parentCursor
) RETURN ParentArray
PIPELINED
;
FUNCTION countSomething(some params…)
RETURN INT;
FUNCTION checkCondX (SomeParent IN ParentRecordType)
RETURN VARCHAR2;
FUNCTION checkCondY (SomeParent IN ParentRecordType)
RETURN VARCHAR2;
PROCEDURE GET_PARENT_RECORDS( other_parameters, Parents OUT THIS_PKG.parentCursor);
PROCEDURE GET_CHILD_RECORDS( other_parameters, Children OUT THIS_PKG.childCursor);
END THIS_PKG;
パッケージ本体
-- omitted
FUNCTION processParents(
p IN THIS_PKG.parentCursor
) RETURN ParentArray
PIPELINED
IS
out_rec ParentArray;
someParent ParentRecordType;
BEGIN
LOOP
FETCH p BULK COLLECT INTO out_rec LIMIT 100;
FOR i IN 1 .. out_rec.COUNT
LOOP
out_rec(i).extra_column_A := countSomething (out_rec(i).field1, out_rec(i).field2);
out_rec(i).extra_column_B := checkCondX(out_rec(i));
out_rec(i).extra_column_C := checkCondY(out_rec(i));
pipe row(out_rec(i));
END LOOP;
EXIT WHEN p%NOTFOUND;
END LOOP;
RETURN;
END processParents;
PROCEDURE GET_PARENT_RECORDS(
some_columns,
Parents OUT THIS_PKG. parentCursor) IS
BEGIN
OPEN Parents FOR
SELECT *
FROM TABLE(processParents (CURSOR(
SELECT *
FROM (
--some select statement with quite a few where clause
--to simulate dynamic search (from pre-canned search options)
)
))) abc
WHERE abc.extra_column_C like '%xyz%' --(xyz is a user given value)
;
END GET_PARENT_RECORDS;
更新 昨日、調査を行ったところ、(Toad の) Quest Batch SQL Optimizer に出会いました。パッケージを差し込んで、これが私が得たものです。
バッチ オプティマイザーの結果
複雑なクエリ
問題のあるクエリ