内部結合と場所


257

(オラクルで)パフォーマンスに違いはありますか

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

そして

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID


1
参考

12
@BlackTigerX:異なる結果?関与する外部結合はありましたか?句にinner join ... on同等の結合基準を配置することと比較することで異なる結果がどのように発生するかはわかりませんwhere
シャノン退職

古いバージョンのoracleデータベースには存在しませんjoin
MajidTaheri

2
@MajidTaheri:あなたは何バージョンのOracleについて話しているのですか?OracleでサポートされているすべてのバージョンがJOIN表記をサポートしています。
ジョナサンレフラー

些細なケースに基づく一般的な回答やベストプラクティスを探します。複数のAND条件が含まれる、より複雑なwhere句との「再照合」が必要です。少なくともSQL Serverには、クロスオーバーポイントがあります。
crokusek 2013

回答:


195

番号!同じ実行プランで、次の2つのテーブルを見てください。

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

内部結合を使用したクエリの実行プラン:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

そして、WHERE句を使用したクエリの実行プラン。

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

4
私は本当にこのことについて言っオラクルからの公式文書があるかどうかを確認したいです
4のままにカバー

68

クエリオプティマイザーが正しく機能している場合、これらのクエリに違いはありません。これらは、同じ望ましい結果を指定するための2つの方法にすぎません。


22
ええ、パフォーマンスは同じでなければなりません。しかし、SELECT * FROM Table1、Table2 WHERE ...構文は悪です!
Joel Coehoorn、2008

2
SQL-92構文よりもFOR INNER JOINSを理解する方がはるかに簡単です。あなたのマイレージは異なる場合があります。
クレイグトレーダー

25
WHERE構文はINNER JIONよりも読みやすいと思います。これはVegemiteに似ていると思います。世界のほとんどの人はそれを嫌だと思うかもしれませんが、それを食べて育った子供たちはそれを愛しています。
ScottCher 2008年

3
ベジマイトは確かに厄介ですが、それでも私はスクラップルが大好きです。図を行きます。
StingyJack 2009

2
@Darryl JOINテーブルを結合するための条件は、WHERE句の「どこかに」ではなく、すぐに定義されているため、sは読みやすいと思います。テーブルの相互関係(たとえば)を定義するのではなくWHERE、データセットを制限するための節(たとえばWHERE DATE > (SYSDATE - 1))を予約することを好みWHERE T1.ID = T2.IDます。問題の例のような小さなテーブルの場合はほとんど違いがありませんが、複数のテーブルと複数の条件を含む大きなクエリの場合は、クエリがはるかに理解しやすくなると思います。
ImaginaryHuman072889

61

それらはまったく同じでなければなりません。ただし、コーディングの実践として、私はむしろ結合を参照したいと思います。それは明らかにあなたの意図を明確にします、


8
同意する。特に、複数のテーブルに結合する場合、明示的な結合を行うと、selectステートメントを解析する方がはるかに簡単になります。
ポール・森江

13
確かに。結合は、2つのデータセット間の意味的な関係を表しますが、whereはフィルタリングされたセットを示します。+1
EightyOne Unite 2011

26

JOINコードを使用すると、説明がわかりやすいのでコードが読みやすくなります。

速度に違いはなく(テストしたばかりです)、実行プランは同じです。


ありがとうございました。私はこの2つの方法の間の速度圧縮を探していました。
Farhad Navayazdan 16

14

Oracleについては知りませんが、SQL Serverでは古い構文が廃止されており、最終的にはなくなる予定です。新しいクエリでその古い構文を使用する前に、Oracleがその構文をどう処理するかを確認しました。

結合基準を他の必要なwhere条件と混合するのではなく、新しい構文を使用します。新しい構文では、何が結合を作成し、他にどのような条件が適用されているかがより明確になっています。このような短いクエリではそれほど大きな問題ではありませんが、より複雑なクエリを作成すると、混乱がさらに大きくなります。人々は基本的なクエリについて学習するので、複雑なクエリでそれが必要になる前に、結合構文の使用を学ぶことを好む傾向があります。

また、Oracleについて具体的には知りませんが、SQL Server 2000でも古いスタイルの左結合のSQL Serverバージョンに欠陥があり、一貫性のない結果(左結合がクロス結合になることもある)が発生することを知っています。中古。うまくいけば、Oracleが同じ問題に悩まされることはありませんが、確かに、左と右の結合は、古い構文で適切に表現するのが非常に難しい場合があります。

さらに、ANSII標準の結合を使用する開発者は、結合とは何か、および結合の意味を理解する傾向があるというのは、私の経験です(もちろん、これはあくまで個人的な意見であり、経験は異なる場合があります)。データベースからのデータ。データベースをよく理解しているほとんどの人は、より複雑なクエリを書く傾向があり、古いスタイルよりもANSII標準を使用して保守する方がはるかに簡単に思えるので、私は信じています。


1
アーメン兄弟。ジョイナーズダウン!!
ScottCher 2008年

14

【おまけポイントに…】

JOIN構文を使用すると、結合がすべて1行に含まれているため、結合をより簡単にコメント化できます。これ、複雑なクエリをデバッグする場合に役立ちます。

他の誰もが言うように、機能的には同じですが、JOINは意図の表明をより明確にします。したがって、あり、それは、特定の場合には、現在のOracleのバージョン(私はそれがない場合は考えている)のいずれかで、クエリオプティマイザを助けることがオラクル(誰がどんな考えを持っていない)の将来のバージョンでは、クエリオプティマイザを助ける、またはそれが可能ならば助けますデータベースのサプライヤを変更します。


2
または... INN JOINSをLEFT JOINSに簡単に変更して、どの結合が予期した行を見逃しているのかを確認できます。これは、クエリ全体を一度に行うためです。INNER JOINSをコメントアウトする場合は、除去のプロセスを実行する必要があります。時間がかかります。ただし、+ 1は、読みやすさを除いて、これがINNER JOINSの私のお気に入りの理由の1つであるためです。
Matthew McPeak 2015

13

それらは論理的には同じですが、ANSI構文を採用した以前のバージョンのOracleでは、より複雑なケースでバグが発生することが多かったため、Oracle開発者からの抵抗に遭遇することがあります。


以前のバージョンのOracleには、これに関するバグがありましたか?どれくらい早いですか?どのバージョンですか?
ScottCher 2008年

メタリンクには詳細があります...それらはあちこちにポップアップ表示されます。
David Aldridge、

7

パフォーマンスは同じでなければなりませんが、外部結合に関しては明確さが向上するため、結合バージョンを使用することをお勧めします。

また、意図しないデカルト積は、結合バージョンを使用して回避できます。

3番目の効果は、より単純なWHERE条件でSQLを読みやすくすることです。


重要なのは、基準が曖昧な場合の意図しない影響です。結合のタイプを指定すると、取得する内容が正確にわかります。異なるデータベースや、同じデータベースプラットフォームの異なるバージョンでも、暗黙の結合ではnull値が異なる方法で処理されることがわかりました。left / right inner / outerを指定するときは、どちらが正しいかを考える時間を費やします。あいまいな方法を使用するときは、それが希望どおり/意図したとおりに機能すると想定します。
Steve Kallestad、2014年

6

Oracleでは、結合キー属性の名前が両方のテーブルで同じである場合は、次のように書くこともできます。

select *
from Table1 inner join Table2 using (ID);

もちろん、これも同じクエリプランです。


以前の改訂で回答の意味が変更されたため、エディションをロールバックしました
juan

5

テーブルが第3正規形であるシナリオでは、テーブル間の結合は変更されません。つまり、顧客と支払いに常に参加する必要があります。

ただし、結合フィルターは区別する必要があります。結合は関係についてであり、フィルターは全体を分割することについてです。

標準に言及している著者もいます(Jim Melton、Alan R. Simon(1993)。新しいSQLの理解:完全なガイド。MorganKaufmann、11〜12ページ。ISBN978-1-55860-245-8。)は、FROM句でカンマ区切りのテーブルよりもJOIN構文を採用するメリットについて書いています。

私はこの見解に完全に同意します。

SQLを記述して同じ結果を得るにはいくつかの方法がありますが、チームワークを行う人の多くにとって、ソースコードの読みやすさは重要な側面であり、テーブルを特定のフィルターからどのように関連付けるかを確実に分離することは、ソースを明確にするという意味で大きな飛躍でしたコード。


内部結合は、クロス結合の場所を意味します。カンマはキーワード結合よりも優先順位が低いクロス結合です。on vs "filter"は内部結合には関係ありません。NFはクエリとは無関係です。標準では、キーワード結合をコンマで促進するものはありません。些細な最適化は、どこでも同じように扱います。この答えは誤解の束です。
philipxy

1)@philipxyは「コンマで区切られたFROM句のテーブルはCROSS JOINされたテーブルと同じ意味を持っている」と言っていると思います。私はそれに同意します。もちろん、古い構文に固執することができ、それはJOIN句と共存できます。RDBMSオプティマイザは両方のケースを同じものとして完全に理解し(もちろん同等である場合)、同じ計画を作成します。
abrittaf


2

これらは両方とも同じことを行う内部結合です。1つは単に新しいANSI構文を使用するだけです。


2

機能的には、言われているのと同じです。ただし、結合を行う方が、やりたいことを正確に説明するのに適していることに同意します。結合を開始し、頭の中で元のクエリとは異なるクエリを実行したいことに気づくまで、何度もクエリを実行する方法を知っていると何度も思っていました。


1

機能的には、両方のクエリを同じ方法で処理する必要があります。ただし、新しい結合構文を使用するビューから選択する場合は、それも使用してクエリを構造化することが重要であることが経験からわかっています。ビューが「結合」ステートメントを使用する場合、Oracleのオプティマイザーは混乱する可能性がありますが、ビューにアクセスするクエリは、「WHERE」句で結合する従来の方法を使用します。


これは、結合よりもビューの方が問題です。
存在しない

0

2つのクエリの同一性は明らかであるように見えますが、いくつかの奇妙なことが起こります。結合述語をJOINからOracle 10gのWHEREに移動すると、クエリの実行プランが異なるクエリに遭遇しました(WHEREプランの方が優れています)が、この問題を簡略化されたテーブルとデータで再現することはできません。それは私のデータと統計に依存すると思います。オプティマイザーは非常に複雑なモジュールであり、魔法のように動作する場合があります。

DBの内部に依存しているため、この質問に一般的に答えることはできません。しかし、答えは「違いなし」でなければならないことを知っておくべきです。


0

本番環境でのspのタイムアウトの1つを検査し、代わりにxmlフィードから構築されたテーブルの内部結合を「where」句に変更したとき、今日この難題に直面しました。平均execが2.2秒になる前...実行プランの主な違いは、キールックアップの消失です...両方の方法を使用してテストするまでメッセージはわかりません。

乾杯。



0

キーウィックが言ったように、実行計画は同じです。

JOINステートメントの方が読みやすいだけなので、ON条件を忘れずにデカルト積を取得できます。これらのエラーは、SELECT * FROM t1、t2 WHERE t1.id = t2.some_fieldタイプの複数の結合を使用する長いクエリで検出するのが非常に難しい場合があります。

結合条件を1つだけ忘れると、クエリを実行するのに非常に長い時間がかかり、非常に多くのレコードが返されます。一部の人々はDISTINCTを使用してクエリにパッチを当てていますが、実行するのにまだ非常に長いです。

それが正確に理由です。JOINステートメントを使用することは確かにベストプラクティスです。つまり、保守性と可読性が向上します。

さらに、よく覚えていますが、JOINはメモリ使用量に関して最適化されています。


0

私はその良い答えに追加があります

これがそれぞれSQL92とSQL89として定義されています。INNERという単語は省略できますが、それらの間にパフォーマンスの違いはありません(JOINを使用するだけで十分明確であり、最も単純なクエリでは5つのキーボードストロークを保存すると、大きなストロークがいくつあるかを想像できます。もの)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.