0

動的クエリ文字列を作成して実行するこのストアド プロシージャがあります。SP は開発およびテスト環境では問題なく動作ますが、クライアント企業の DBA は、このクエリが本番環境のデータベースに非常に大きな打撃を与えていると報告しています。IT 部門からクエリの調整を依頼されました。これまでのところ、この SP のほとんどすべてを、クエリ文字列を動的に構築することから、(古いクエリと比較して) 非常に高速に実行される単一の大きなクエリに移動しました。

パラメータにデフォルト値または実際の値があるかどうかを評価することにより、sp がクエリ文字列の where 句を作成することを (とりわけ) 発見しました。

IF P_WORKFLOWSTATUS <> 0 THEN
    L_SQL := TRIM(L_SQL) || ' AND WORKFLOW.STATUS = ' || TO_CHAR(P_WORKFLOWSTATUS);
END IF;

したがって、この動作を次のように最適化しました。

WHERE
    ...
    AND (WORKFLOW.STATUS = P_WORKFLOWSTATUS OR P_WORKFLOWSTATUS = 0)

この種の変更により、数値列に影響を与えていたクエリが改善されましたが、VARCHAR2 パラメータと列に問題があることがわかりました。現在の挙動は

--CLIENT.CODE is a VARCHAR2(14) column and there is an unique index for this column.
--The data stored in this field is like 'N0002077123', 'E0006015987' and similar
IF NVL(P_CLIENT_CODE, '') <> '' THEN
    L_SQL := TRIM(L_SQL) || ' AND CLIENT.CODE = ''' || P_CLIENT_CODE || '''';
END IF;

実行して、これを最適化されたバージョンのクエリに変更しようとしました

WHERE
    ...
    AND (CLIENT.CODE = P_CLIENT_CODE OR NVL(P_CLIENT_CODE, '') = '')

しかし、この変更により、クエリのパフォーマンスが低下しました。VARCHAR2クエリのこの部分を最適化する方法はありますか? または、このパラメーターを where 句に追加する必要があるかどうかを評価するためだけに、大きなクエリを動的クエリに (再び) 変換する必要がありますか?

前もって感謝します。

4

3 に答える 3

2

Oracle は空の文字列''を NULL として扱います。したがって、この条件NVL(P_CLIENT_CODE, '') = ''はあまり意味がありません。さらに、ここでは常に false である NULL の等価性をチェックしているため、常に false になります。そのために、クエリのその部分を次のように再コーディングする必要があります。

WHERE
    ...
    AND ( (CLIENT.CODE = P_CLIENT_CODE) OR (CLIENT IS NULL) )
于 2012-12-14T07:05:50.160 に答える
0

もちろん、すでに述べたように、正しいnullチェックを実行する必要があります。

ただし、秘訣は、

AND (CLIENT.CODE = P_CLIENT_CODE OR NVL(P_CLIENT_CODE, '') = '') 

AND ( (CLIENT.CODE = P_CLIENT_CODE) OR (CLIENT IS NULL) )

単独でパフォーマンスの問題を引き起こす可能性はほとんどありません。2番目の句を使用したクエリは、最初の句を使用したクエリよりもパフォーマンスが低下する可能性があります。これは、より多くの行に対してtrueが生成され、結果として生じる結合/順序/ファイラーなどの結果セットが大きくなるためです。

この句をクエリに追加すると、最適な実行プランがどういうわけか壊れてしまうことは間違いありません。client.codeたとえば、廃止された統計がある場合、オプティマイザは、他の利用可能なインデックスの代わりに非選択的なインデックスを選択するという次善の決定を下す可能性があります。

explain planただし、低速クエリの実際の実行プラン(コマンドで取得する予期されたものではありません!)とテーブル構造を確認しないと、確実に判断するのは困難です。

于 2012-12-14T07:29:07.600 に答える