(Oracleの)パフォーマンスに違いはありますか
Select * from Table1 T1
Inner Join Table2 T2 On T1.ID = T2.ID
そして
Select * from Table1 T1, Table2 T2
Where T1.ID = T2.ID
?
番号!同じ実行計画で、次の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
クエリオプティマイザーが適切に機能している場合、これらのクエリに違いはありません。同じ望ましい結果を指定するための2つの方法にすぎません。
それらはまったく同じでなければなりません。ただし、コーディングの慣例として、私はむしろ参加を見たいです。明確にあなたの意図を明確にし、
JOIN
を使用すると、一目瞭然なのでコードが読みやすくなります。
速度に違いはありません(テストしたところ)、実行計画は同じです。
Oracleについては知りませんが、古い構文はSQL Serverで非推奨になり、最終的にはなくなることを知っています。その古い構文を新しいクエリで使用する前に、Oracleがそれをどのように使用する予定かを確認しました。
私は、結合条件と他の必要なwhere条件を混合するよりも、新しい構文を好みます。新しい構文では、何が結合を作成し、他のどの条件が適用されているかがはるかに明確です。このような短いクエリではそれほど大きな問題ではありませんが、より複雑なクエリを使用すると、さらに混乱を招きます。基本的なクエリで学習するので、複雑なクエリで必要になる前に結合構文を使用することを学習する方を好む傾向があります。
繰り返しますが、Oracleの具体的な知識はありませんが、SQL Serverバージョンの古いスタイルの左結合にはSQL Server 2000でも欠陥があり、一貫性のない結果(時には左結合、クロス結合)が発生することがわかっています。中古。 Oracleが同じ問題に悩まされないことを願っていますが、確かに左と右の結合は古い構文で適切に表現するのがむずかしいかもしれません。
さらに、ANSII標準結合を使用する開発者は、結合とは何か、それを取得するという意味についてよりよく理解する傾向があるのは、私の経験でした(もちろん、これは厳密に個人的な意見です。異なる経験があるかもしれません)。データベースからのデータ。データベースを十分に理解しているほとんどの人は、より複雑なクエリを記述する傾向があるため、ANSII標準を使用すると、古いスタイルよりもはるかに簡単にメンテナンスできるように思えます。
[ボーナスポイントについて...]
JOIN構文を使用すると、結合がすべて1行に含まれるため、結合をより簡単にコメントアウトできます。このcanは、複雑なクエリをデバッグする場合に役立ちます
他の誰もが言うように、それらは機能的には同じですが、JOINは意図の記述をより明確にしています。したがって、may特定の場合に現在のOracleバージョンでクエリオプティマイザーを支援します(そうするかどうかわかりません)、may Oracleの将来のバージョンでクエリオプティマイザーを支援します(誰も考えていない)、またはmayデータベースサプライヤを変更する場合に役立ちます。
論理的には同じですが、ANSI構文を採用したOracleの以前のバージョンでは、より複雑なケースでバグが頻繁にあったため、使用時にOracle開発者から抵抗を受けることがあります。
パフォーマンスは同じである必要がありますが、外部結合に関しては明確さが向上しているため、結合バージョンを使用することをお勧めします。
また、join-versionを使用すると、意図しないデカルト積を回避できます。
3番目の効果は、より単純なWHERE条件でSQLを読みやすくすることです。
Oracleでは、結合キー属性の名前が両方のテーブルで同じであるということを忘れないでください。これを次のように書くこともできます。
select *
from Table1 inner join Table2 using (ID);
もちろん、これにも同じクエリプランがあります。
PostgreSQLでは、間違いなく違いはありません-それらは両方とも同じクエリプランに相当します。 Oracleの場合も99%確信しています。
テーブルが3番目の標準形式であるシナリオでは、テーブル間の結合は変更されません。つまり顧客に参加し、支払いは常に同じままである必要があります。
ただし、joinsとfiltersを区別する必要があります。結合は関係に関するものであり、フィルターは全体の分割に関するものです。
SQL-92構文は、両方の概念を分離することを奨励し、結合とフィルターの両方をWHERE句に置く古い構文よりも優先されます。
機能的には、前述のとおりです。私は、あなたが何をしたいのかを正確に説明するために、結合を行う方が良いことに同意します。結合を開始するまで、何かをクエリする方法を知っていて、頭の中で元のクエリとは異なるクエリを実行したいことに気づいたのだと思いました。
どちらも同じことを行う内部結合であり、単純に新しいANSI構文を使用します。
機能的には、両方のクエリを同じ方法で処理する必要があるのは事実です。ただし、新しい結合構文を使用するビューから選択する場合、それを使用してクエリを構造化することも重要であることが経験により示されています。ビューが「結合」ステートメントを使用する場合、Oracleのオプティマイザーは混乱する可能性がありますが、ビューにアクセスするクエリは、「where」句で結合する従来の方法を使用します。
キーウィクが言ったように、実行計画は同じです。
JOINステートメントは読みやすく、ON状態を忘れずにデカルト積を取得しやすくなります。これらのエラーは、SELECT * FROM t1、t2 WHERE t1.id = t2.some_fieldタイプの複数の結合を使用する長いクエリで検出するのは非常に困難です。
結合条件を1つだけ忘れると、非常に多くのレコードを返すクエリを実行するのに非常に長い時間がかかります。本当に多すぎます。一部の人々はDISTINCTを使用してクエリにパッチを当てていますが、それでも実行には非常に時間がかかります。
それがまさに、JOINステートメントを使用することがベストプラクティスである理由です。つまり、保守性と読みやすさが向上します。
さらに、覚えていれば、JOINはメモリ使用量に関して最適化されています。
2つのクエリのIDは明らかなように見えますが、時々奇妙なことが起こります。 Oracle 10gで結合述語をJOINからWHEREに移動するときに異なる実行プランを持つクエリが発生しました(WHEREプランの方が優れています)が、単純化されたテーブルとデータではこの問題を再現できません。私のデータと統計に依存すると思います。オプティマイザーは非常に複雑なモジュールであり、魔法のように動作することもあります。
DB内部に依存しているため、一般的にこの質問に答えることができないのはそのためです。しかし、答えは「違いなし」でなければならないことを知っておく必要があります。
それらは両方とも結合であり、それが同じことをする場所です。
本日、spの実稼働中のタイムアウトを検査し、代わりにxmlフィードから作成されたテーブルの内部結合を 'where'句に変更したときに、この難問がありました。平均実行前は2.2秒でした...実行計画の主な違いは、キールックアップの消失です...両方の方法を使用してテストするまでわからないメッセージです。
乾杯。