1

Null になる可能性がある Bind-Variables を使用する Select ステートメントが多数あります。Null は、Bind-Value がステートメントを制限してはならないことを意味します。

以下は、私たちが行っている簡単な例です。

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

create index IPERSON1 on PERSON(NAME, ID);

begin
dbms_stats.gather_table_stats(user, 'PERSON');
end;

select * from PERSON
where NAME = nvl(:b1, NAME);

select * from PERSON
where (NAME =:b1 or :b1 is null);

2 つのステートメントには、次の実行計画があります。

select * from PERSON where NAME =nvl(:b1, NAME): 
------------------------------------------------------------------------------------
| Id  | Operation              | Name     | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |        |       |     4 (100)|          |
|   1 |  CONCATENATION         |          |        |       |            |          |
|*  2 |   FILTER               |          |        |       |            |          |
|*  3 |    INDEX FAST FULL SCAN| IPERSON1 |    500 |  7500 |     2   (0)| 00:00:01 |
|*  4 |   FILTER               |          |        |       |            |          |
|*  5 |    INDEX RANGE SCAN    | IPERSON1 |      1 |    15 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------

select * from PERSON where (NAME =:b1 or :b1 is null): 
-----------------------------------------------------------------------------
| Id  | Operation         | Name   | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |        |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| PERSON |     26 |   390 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

では、そのような外部結合に最適なソリューションは何だと思いますか?

4

1 に答える 1

2

特定のテーブルスキーマと利用可能なインデックスに依存するため、質問に一般的に答えられるとは思いません。

一般的に言えることは次のとおりです。

  • 両方の提案された WHERE 条件は、インデックス ルックアップを介して関連する行を直接見つけることができません。代わりに、テーブルまたはインデックスのいずれかを完全にスキャンする必要があります。

  • 同じクエリの異なるバリエーションを 1 つにマージすることはアンチパターンと見なされます。これは、Oracle がすべてのバリエーションに対して同じ実行計画を使用する必要があるためです。

したがって、おそらく次のいずれかを実行することをお勧めします。

  1. クエリを動的に作成します。つまり、パラメータが null でない場合にのみ WHERE 条件を追加します。WHERE 条件が存在する場合でも、最適なパフォーマンスに不可欠なバインドされたパラメーターを使用する必要があります。

  2. または、パラメーターが null かどうかに応じて別のクエリを実装します。

オプション 1 が推奨オプションです。C#、Java、または同様の言語のクエリを実行すると、おそらく実装が簡単になります。

オプション 2 は、おそらく PL/SQL から使用するものです。ただし、null になる可能性のあるパラメーターが複数ある場合は、さまざまなクエリが発生する可能性があります。

于 2012-12-03T15:12:58.970 に答える