OracleのEXISTS句で質問です。


EXISTSの後のSELECT文で

WHERE EXISTS (SELECT NULL ...
WHERE EXISTS (SELECT 'X' ...
WHERE EXISTS (SELECT 1 ...

のようにいろいろな書き方ができると思いますが、実際にどれが理想なのか説明しているサイトはありますか?

Oracleのディクショナリビューは「exists (select null・・・」としているものが多いようなんですが・・・
http://otn.oracle.co.jp/forum/thread.jspa?threadID=8008219&tstart=4227

回答の条件
  • 1人2回まで
  • 登録:2008/10/22 08:19:05
  • 終了:2008/10/29 08:20:02

回答(3件)

id:chuken_kenkou No.1

chuken_kenkou回答回数722ベストアンサー獲得回数542008/10/22 11:32:39

ポイント27pt

標準SQLなどでは、

[NOT} EXISTS (SELECT * FROM ~)

という例が多いです。

しかし、EXISTS使用時、「SELECTの選択リストでは、選択式を1個しか指定できない」という原則を、厳密にチェックしているRDBMSもあり、「*」ではエラーになってしまう場合があります。そういったRDBMSでは、

[NOT} EXISTS (SELECT 1 FROM ~)

といった例題が使われている場合が多いです。

id:takerudayo No.2

takerudayo回答回数165ベストアンサー獲得回数292008/10/22 10:00:57

ポイント27pt

的確に説明しているサイトは知りませんがここで考えを書いては駄目でしょうか。駄目ならポイント無しでいいです。


どれが理想との事ですが、いくつかの見方があるかと考えました。


できるだけSQLが早くなるのが理想だとすると、

「DBを高速化する一般的な考えは副問いも含めて全ての工程で出来る限り処理するデータ量を減らすこと」

だと考えられます。

そうなると質問に書かれているような記述方法の中から一番使用バイト数が少ない文字で行くのが

正しいと考えていいと思います。


次に早いSQLも欲しいけどSQLの見易さも理想だとすると、

http://www.shift-the-oracle.com/inside/in-exists-difference.html...

に書かれている通り、1とかの記述はよくないSQLと考えた方が良いと思います。


これらを踏まえると、

できるだけSQL処理が早くすみ、説明無くても意味が伝わる記述として、私は以下のような記述をお勧めします。


SELECT 出力カラム

FROM テーブル1

WHERE EXISTS (SELECT PKカラム or 評価条件部で使われるIndexと同等のカラム FROM テーブル2 WHERE 評価条件部)


この記述で目指しているのは、評価条件部で評価するのにDBがDBFから抽出したデータをそのままEXISTS内の出力カラムに使えば

DBとしては再度テーブル2からのデータ読み込み処理負荷がかからないという事で出来る限りの負荷減を目指している記述です。


参考になればと思います。

id:chuken_kenkou No.3

chuken_kenkou回答回数722ベストアンサー獲得回数542008/10/23 11:01:00

ポイント26pt

#1です。

#2回答者さんの意見に少し異議があるので、参考までに。

できるだけSQLが早くなるのが理想だとすると、

「DBを高速化する一般的な考えは副問いも含めて全ての工程で出来る限り処理するデータ量を減らすこと」

だと考えられます。

そうなると質問に書かれているような記述方法の中から一番使用バイト数が少ない文字で行くのが正しいと考えていいと思います。


次のような場合は、性能に大きく影響します。

  • 検索条件でインデクスを有効利用できるか
  • ORDER BY、GROUP BY、DISTINCTなど、ソートが必要な処理で、作業メモリ・作業ファイルを使用したソートが発生するか、インデクスを有効利用してそれらのソートを抑止できるか
  • 選択リストで指定する列数が多いorバイト数が相当に大きな列を操作

SELECTの選択リストの値が1バイト小さくなる程度では、性能上はゴミのようなものです。

次に早いSQLも欲しいけどSQLの見易さも理想だとすると、

http://www.shift-the-oracle.com/inside/in-exists-difference.html...

に書かれている通り、1とかの記述はよくないSQLと考えた方が良いと思います。

「ちなみに、EXISTS の中の 副問い合わせには、'SELECT * FROM ~'を使用するより 'SELECT 1 FROM ~' などの固定項目を使用した方が早い(CBOでは過去形の可能性が大)。ただこれを知らない人がみると ???...何だこれ? になるので要注意なうえ、既に時代遅れの技に近いかもしれない。」

上記URLの記述は、

『「*」でなく「1」と記述した方が、過去には早いことがあったが、これを知らない人が見ると???になることがある。現在は「*」と書いても、オプティマイザが効率的に処理してくれる場合が多い』

といった意味で、「1」を指定するのはよくないとまでは言っていません。

SELECT 出力カラム

FROM テーブル1

WHERE EXISTS (SELECT PKカラム or 評価条件部で使われるIndexと同等のカラム FROM テーブル2 WHERE 評価条件部)

一番使用バイト数が少ない文字で行く


上記の二つは、「矛盾するのでは?」と思います。

国産RDBMSの開発に長年携わり、オプティマイザの内部処理についても一般の人よりは詳しい者からの意見です。参考まで。

id:teppei0507

どうもありがとうございます。確かに、

>「DBを高速化する一般的な考えは副問いも含めて全ての工程で出来る限り処理するデータ量を減らすこと」

という視点であれば、「1」という書き方がいいのでは?と感じました。

ただし、現在のRDBであれば、

>「*」と書いても、オプティマイザが効率的に処理してくれる場合が多い』

ということなら、「*」でもいいわけですね(通常私はOracle9.2を使っています、問題ないかと考えます)。

いろいろ参考になります、どうもありがとうございます。

ちなみに、もしご存知であれば

 EXISTS (SELECT NULL ~

という記述には問題があるかどうか教えていただきたいです。

NULLであれば後工程の処理が減るのではないか?と少し思うのですが。。。

2008/10/26 23:05:43
  • id:chuken_kenkou
    >しかし、EXISTS使用時、「SELECTの選択リストでは、選択式を1個しか指定できない」という原則

    失礼。上記の原則は誤り。

    existsで指定したサブクエリ中で、intersect、exceptなど、積や差分を求める場合に関しては、サブクエリ中のselect句で1個以上の意味のある指定が必要な点を考慮漏れしてました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません