0

テーブルX

number doc
number item
number parentItem

データあり:

1, 1000, 0
1, 1010, 1000
1, 1020, 1000
1, 2000, 0
1, 2010, 2000


テーブル Y

number doc
number item
varchar2(16) SomeData

データあり:

1, 1000, "1000 Data"
1, 2000, "2000 Data"


次の SQL クエリを使用して、TableY から "SomeData" を取得します。

select x.doc, x.item, y.SomeData from TableX x
join TableY y
on y.doc = x.doc and y.item IN (x.item, x.ParentItem)

結果は次のようになります。

1, 1000, "1000 Data"
1, 1010, "1000 Data"
1, 1020, "1000 Data"
1, 2000, "2000 Data"
1, 2010, "2000 Data"

私の質問は次のとおりです。INステートメントは順番に評価されますか、それともOracleがたどるパスに依存しますか?


編集 TableX の項目 (1000 など) の TableY にエントリがある場合、この値は JOIN で最初に使用されますか、それとも ParentItem が最初に使用されますか? または、ParentItem の JOIN は、アイテムの JOIN が失敗した場合にのみ実行されますか?

4

2 に答える 2

4

一般に、データベースを操作する場合、指定しない限り順序はありません。IN一致が見つかったときにショートサーキットするのではなく、常にリスト全体を調べると思いますが、リストが処理される順序についての保証はありません (リスト全体をチェックしているかどうかは重要ではありません)。


修正された質問に基づいて:

Oracle は、行の内容に基づいて実行計画を作成することはできないため、オプティマイザは、可能な限り最も効率的な方法で両方の列を検索する計画を作成します。その計画がどうなるかは、作成したテーブルとインデックスのサイズに大きく依存します。

ほとんどの場合、テーブルを 1 回処理する方が高速であるため、オプティマイザーは、一度に 1 つずつ列を調べる必要があるルートよりも、両方の列を簡単に調べることができるルートを選択する可能性があります。これは、より良い方法がない限り、テーブル全体のスキャンが行われる可能性が高いことを意味します。少し実験してみると、両方の列をカバーするインデックスがあったとしても、オプティマイザはフル テーブル スキャンを選択することがわかりました。

興味深いことに、これは、2 つの列を別々にインデックス化した方がよい数少ないシナリオの 1 つです。両方の列に個別のインデックスがある場合、オプティマイザは両方のインデックスをスキャンし、abitmap orを使用して各結果セットから一意の行 ID のセットを取得するようです。

ここでの注意点は、非常に人為的なシナリオを使用して、利用可能な大きなテーブルで調査が行われたことです。最も単純で読みやすく (そして維持しやすい) 方法でクエリを作成し、実際のパフォーマンスをテストして、自分で説明計画を確認する必要があります。パフォーマンスの問題がある (またはその可能性が高い) と判断した場合にのみ、別のより効率的な (ただしおそらく自明ではない) クエリの記述方法を探す必要があります。一般に、よく考え抜かれた検索可能なクエリがあれば、オプティマイザは利用可能な最も効率的なパスをうまく選択します。

于 2011-07-25T13:50:20.407 に答える
0

評価の順序は関係ありません。IN ステートメントは、単純にy.item = x.item OR y.item = x.ParentItem OR ....

于 2011-07-25T13:30:21.150 に答える