外部結合と等価結合のパフォーマンスの違いについて(ビューの場合)

このQ&Aのポイント
  • Oracle10gでのSQL文における外部結合と等価結合のパフォーマンスの違いについて教えてください。
  • ビューの場合も同じような現象が起きることがありますが、外部結合ありのほうが結果がすぐに返されるのに対して、外部結合なしのほうは結果が返ってこないか時間がかかることがあります。
  • 重い処理が含まれるSELECT句やオプティマイザの実行計画などがパフォーマンスに影響している原因と考えられます。どちらのSQL文でパフォーマンスの問題が起きているのか詳しく説明してください。
回答を見る
  • ベストアンサー

外部結合と等価結合のパフォーマンスの違いについて(ビューの場合)

Oracle10gでのSQL文の違いについて教えて下さい。 前回の質問は、ストアドプロシージャに記述 されていて、バッチとして動かしています。 と書きましたが、ビューの場合のパフォーマンスの違いは どうなるのでしょうか?ビューの場合も同じような現象です。 下記の2つのSQL文は外部結合ありと外部結合なしの違いだけで、 他は変わりありません。 外部結合ありのほうは 結果がすぐに返されるのですが、外部結合なしのほうは 結果が返ってこない、あるいはかなり時間がかかるという 現象が起きています。 SQL文は簡略して記述していますが、SELECT句には、 TO_CHAR()やSUM(CASE WHEN ...THEN ...ELSE...)が使用してあり 少し重くなる処理も含まれています。 この2つのSQL文でパフォーマンスに影響している原因は 何なんでしょうか?オプティマイザとか実行計画とかの 説明を読んだのですが、いまいちよく解りません。。 自分では中級者以下だと思っていますので、わかりやすく 説明して頂けたら助かります。宜しくお願い致します。 (外部結合ありのSQL) SELECT  a.項目1,  a.項目2,  a.項目3,  a.項目4,  a.項目5 FROM  TBL_A a,  TBL_B b WHERE  a.項目1 = b.項目1(+) AND  a.項目2 = b.項目2(+) AND  a.項目3 = b.項目3(+) AND  a.項目4 = b.項目4(+) AND GROUP BY  a.項目1,  a.項目2,  a.項目3,  a.項目4,  a.項目5 (外部結合なしのSQL) SELECT  a.項目1,  a.項目2,  a.項目3,  a.項目4,  a.項目5 FROM  TBL_A a,  TBL_B b WHERE  a.項目1 = b.項目1 AND  a.項目2 = b.項目2 AND  a.項目3 = b.項目3 AND  a.項目4 = b.項目4 AND GROUP BY  a.項目1,  a.項目2,  a.項目3,  a.項目4,  a.項目5

  • Oracle
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

オラクルのオプティマイザは、テーブルの検索の方法を決めますが、外部結合と内部結合で 立案される実行計画に違いがあり、内部結合の方が合理的な検索方法を立案しているので 結果的に、内部結合の方が速いという話なんですが・・ 実行計画を見なければ、判りませんが、 ・外部結合はbに対して全表検索を選択した。 ・内部結合では、bを索引検索を選択した。 ・bの検索量が、bの格納件数のうち、ごく一部なので、全表検索と索引検索では、極端に検索時間が違う。 ということなんだと思います。(推測なので、実は違うかも知れません) オラクルのマニュアルで、パフォーマンスチューニングガイドというマニュアルがあると思うので、 一読されることをお勧めします。 ちなみに、お書きになったSQLは何か変です。 内部結合のSQLは、bの項目を返さないので、実質的にbに存在するかのチェックを行っているに等しいものです。 書き方や流儀の問題で、内部結合が良いのか、exists条件が良いのか、in条件(メンバーシップ検査)が良いのか 変わってくると思いますが、一応理解できるものです。 しかし、外部結合のSQLについては、bを検索するけど、何もしない??理解に苦しむSQLになっています。 基本的に、内部結合より遅くなる外部結合を、わざわざ書いてみた、というように感じます。 (一般論ですが、同じ書き方をしたら、外部結合は内部結合と同等以下です)

OracleNew
質問者

お礼

ご回答ありがとうございます。 とても参考になりました。

OracleNew
質問者

補足

ご回答ありがとうございます。 >ちなみに、お書きになったSQLは何か変です。 >内部結合のSQLは、bの項目を返さないので、実質的にbに存在する>かのチェックを行っているに等しいものです。 このSQL文は簡略しすぎました、bのテーブルからも項目をSELECTしています、すみませんでした。。 その点を踏まえても同じようなご回答になっていましたでしょうか? また、ビューでもストアドプロシージャでも同じようなパフォーマンスになるのでしょうか?

関連するQ&A

  • オラクルで外部結合

    オラクル8iを使用しています。 テーブルを外部結合する場合のパフォーマンスについてお聞きしたいのですが、 下の二つのSQL文でパフォーマンスは変わってくるのでしょうか? (外部結合記号(+)を=の前後につけた場合) SELECT 項目 FROM テーブル1 A, テーブル2 B WHERE A.項目1 = B.項目1(+); SELECT 項目 FROM テーブル1 A, テーブル2 B WHERE B.項目1(+) = A.項目1;

  • SQL 外部結合についての質問

    SQLの外部結合についての質問です。 今テーブルA,B,Cがあるとします。 AはBに対して外部結合。BはCに対して外部結合 というようにする事は出来ますでしょうか。 SQLを実行してもエラーになります (例) select A.* from A,B,c where A.項目1 = B.項目1 (+) and B.項目2 = C.項目2 (+)

  • 外部結合

    外部結合でどうしても理解できないパターンがあるので どなたか詳しい人がいたら教えてください。 ・まず、テーブルは下記のa_tblとb_tblの2テーブルです。  SQL> desc a_tbl;  名前 型  ------ ---------------  A1 CHAR(4)  A2 CHAR(4)  A3 CHAR(1)  SQL> desc b_tbl;  名前 型  ------ -----------  B1 CHAR(4)  B2 CHAR(4)  B3 CHAR(1) ・それぞれの内容は、  SQL> select * from a_tbl;  A1 A2 A3  ---- ---- -  1001 A001 1  1002 A002 0  1003 A003 1  1004 A004 0  1005 A005 1  SQL> select * from b_tbl;  B1 B2 B3  ---- ---- -  1001 B001 1  1002 B002 0  1003 B003 1  1004 B004 0 ・この2つのテーブルに対して、下記のselectを行います。  SQL> select * from a_tbl, b_tbl where b1(+)=a1 and b3(+)='1';  A1 A2 A3 B1 B2 B3  ---- ---- -- ---- ---- --  1001 A001 1 1001 B001 1  1002 A002 0  1003 A003 1 1003 B003 1  1004 A004 0  1005 A005 1 ・私の予想では、下記の様になると思ったのですが、結果は  上記の様になります。  どのような考え方をすれば上記の結果になるのか教えてください。  A1 A2 A3 B1 B2 B3  ---- ---- -- ---- ---- --  1001 A001 1 1001 B001 1  1003 A003 1 1003 B003 1

  • 外部結合のパフォーマンスチューニングできますか

    下のSQL文がパフォーマンスが非常に悪いです。 何かチューニングする方法ありませんか。 Oracle8.1.7  OSはWin2000serverSP2 ◇SQL文 SELECT A.HINCD , B.TANCD ,A.SIZE,A.COLOR FROM TB_TBLA A ,TB_TBLB B WHERE A.KA_CD = B.KA_CD(+)" AND A.HINCD = B.HINCD(+) AND A.JIGYOCD = 1 AND A.BRCD = 20 AND A.BUCD = 300 TB_TBLAの主キーは、JIGYOCD、BRCD、BUCDです。 TB_TBLBの主キーは、KA_CDです。 また、TB_TBLAの件数は、約10万件、TB_TBLBは3万件だとしたら、 読み込み件数は10万*3万件となるのでしょうか。 よろしくお願いします。

  • 外部結合に条件をつけたい

    oracle初心者です。 表A:ID、氏名 表B:ID、入社年、給与 上の表A,Bを、表Aを左辺にしてLEFT JOINする場合に、単純な外部結合では無く、 入社年が2000年以降の表Bのみ結合したい時のSQL文ですが、 select * from 表A LEFT JOIN 表B ON 表A.ID=表B.ID where 表B.入社年 > 2000 または、 select * from 表A,表B where 表A.ID=表B.ID(+) and 表B.入社年 > 2000 のように記述して実行すると、内部結合になってしまいます。 これを(外部結合として)実現するには、どのように記述すればよいでしょうか? 宜しくお願いいたします。

  • 外部結合での"OR"文

    外部結合で、"AND"の他に"OR"文も使用したいと思います。 しかし、それを実行すると構文エラーになってしまします。 どうしたら上手く出来るのでしょうか? 宜しくお願い致します。 ちなみに、Oracle8iを使用しています。 SELECT test_tbl.tanto_cd,test_tbl.tanto_name, test_tbl.tanto_filecd,test_tbl.tanto_filename FROM test_tbl, test_tbl2 where test_tbl.tanto_cd(+) = test_tbl2.tanto_cd and tanto_filename like '%名%' or test_tbl.tanto_cd = '0000001'; 上記のselect文を流すと 4行でエラーが発生しました。 ORA-01719: OR句またはIN句の中で外部結合は使用できません。 と出てしまいます。

  • 外部結合について

    外部結合というのは、表と表を結合するという事で FROM句に書くべきことと思うのですが、 なぜWHERE句(カラム毎に指定)で指定するのでしょうか? 例えば、 テーブルA No|Kind|Name| ------------- 1|1 |A | 1|2 |B | 2|1 |C | 2|2 |D | テーブルB No|Kind|Data| ------------- 1|1 |10| 外部結合で SELECT A.No, A.Kind, A.Name, B.Data FROM A,B WHERE A.No = B.No(+) AND A.Kind = B.Kind(+) とすると No|Kind|Name|Data| ------------------ 1|1 |A |10| 1|2 |B |NULL| 2|1 |C |NULL| 2|2 |D |NULL| となります。 A.NoがB.NoになくてもOKで、Kindは 完全に一致しないとだめという意味で SELECT A.No, A.Kind, A.Name, B.Data FROM A,B WHERE A.No = B.No(+) AND A.Kind = B.Kind とした場合、 No|Kind|Name|Data| ------------------ 1|1 |A |10| 2|1 |C |NULL| となるのであれば納得いくのですが、 結果は↓なるようです。 No|Kind|Name|Data| -------------------------- 1|1 |A |10| (+)を一つも付けてない場合と 同じ動作になるようです。 テーブルAとテーブルBを結合するとき、 「外部結合する場合はWHERE句で指定する選択の条件全てに(+)を付ける」 「外部結合をしない場合はWHERE句で指定する選択の条件全てに(+)を付けない」 であれば、カラム毎に外部結合演算子を指定する意味が無いと思うのですが。 どなたか、カラム毎に外部結合演算子を指定する意味をご教授下さい。 宜しくお願いします。

  • 複数の表の外部結合について

    Oracle8iを使用して複数の表から特定のデータを抽出するSQL文を作っています。 【表A】 KaiinID | Name ----------------- 11111 | aaaaa ----------------- 22222 | bbbbb ----------------- 44444 | ddddd ----------------- 55555 | eeeee ----------------- 【表B】 KaiinID | Address ------------------- 11111 | address1 ------------------- 44444 | address4 ------------------- 66666 | address6 ------------------- 77777 | address7 ------------------- 【表C】 KaiinID | Memo ----------------- 11111 | Memo1 ----------------- 22222 | Memo2 ----------------- 33333 | Memo3 ----------------- 66666 | Memo6 ----------------- 【欲しい結果】 KaiinID -------- 44444 『A,B,Cの表のうちCのみに存在しないKaiinID』を検索するSQL文を実行したところ、以下のエラーが表示されてしまいました。 Select A.KaiinID From A,B,C Where A.KaiinID=B.KaiinID and A.KaiinID=C.KaiinID(+) and B.KaiinID=C.KaiinID(+); 「3行でエラーが発生しました。  ORA-01417:表が少なくとも1つの他の表に外部結合されている可能性があります。」 このエラーを見ても「外部結合されている可能性?確かにしてるけど・・・」 としかわかりません。 Select A.KaiinID From A,B Where A.KaiinID=B.KaiinID and A.KaiinID not in (Select KaiinID From C); ともしてみたのですが、こちらは実行した途端SQL*Plusが応答なしになってしまいました。 (実際の表にはA,B,Cそれぞれ300万件近いデータがあります) どのようにすれば、『3つの表のうち1つの表のみに存在しないKaiinID』を取得できるのでしょうか? 御存知の方、教えてください!

  • 3テーブル外部結合方法について

    3つのテーブルを外部結合したいのですが・・・、 こんがらがってしまいました。 A,B,Cの3テーブルがあり、A,B,Cの順に外部結合 (LEFT OUTER JOIN)したいのですが、 A,BのテーブルについてはWhere句の条件指定が 必要です。 Select From (Select AA.a From A AA Where b = xxxx) BB Left Outer Join (Select CC.b From B CC Where c = eeee and BB.a = CC.b) On ???? こんな感じでつまづいてしまいました・・・

  • Oracle10gで1つのSQLで複数回同じテーブルを結合する場合のパ

    Oracle10gで1つのSQLで複数回同じテーブルを結合する場合のパフォーマンス向上 Oracleで1つのSQL内で同じテーブルを2回以上結合すると結果出力にかかる時間が非常に遅くなります。 例: SELECT * FROM A, B b1, B b2 WHERE a.id = b1.id AND a.id = b2.id (テーブルBを2回結合している) こういう場合にパフォーマンスを落とさない方法はありますか?テンポラリテーブルでテーブルBのレプリカを作成して使用するというのはなしです。あくまで1つのSQLで結果出力できることを前提にパフォーマンスを向上する方法を教えてください。