[解決済み】SQL ServerにおけるINNER JOINとLEFT JOINのパフォーマンス比較
質問
9つのテーブルに対してINNER JOINを使用するSQLコマンドを作成しましたが、このコマンドには非常に長い時間(5分以上)がかかります。そこで、私の部下がINNER JOINをLEFT JOINに変更することを勧めました。私が知っているにもかかわらず、LEFT JOINのパフォーマンスがより良いからです。私はそれを変更した後、クエリの速度が大幅に改善されました。
なぜLEFT JOINの方がINNER JOINより速いのか知りたいのですが?
私のSQLコマンドは以下のようなものです。
SELECT * FROM A INNER JOIN B ON ... INNER JOIN C ON ... INNER JOIN D
といった具合に
更新してください。 これは私のスキーマの概要です。
FROM sidisaleshdrmly a -- NOT HAVE PK AND FK
INNER JOIN sidisalesdetmly b -- THIS TABLE ALSO HAVE NO PK AND FK
ON a.CompanyCd = b.CompanyCd
AND a.SPRNo = b.SPRNo
AND a.SuffixNo = b.SuffixNo
AND a.dnno = b.dnno
INNER JOIN exFSlipDet h -- PK = CompanyCd, FSlipNo, FSlipSuffix, FSlipLine
ON a.CompanyCd = h.CompanyCd
AND a.sprno = h.AcctSPRNo
INNER JOIN exFSlipHdr c -- PK = CompanyCd, FSlipNo, FSlipSuffix
ON c.CompanyCd = h.CompanyCd
AND c.FSlipNo = h.FSlipNo
AND c.FSlipSuffix = h.FSlipSuffix
INNER JOIN coMappingExpParty d -- NO PK AND FK
ON c.CompanyCd = d.CompanyCd
AND c.CountryCd = d.CountryCd
INNER JOIN coProduct e -- PK = CompanyCd, ProductSalesCd
ON b.CompanyCd = e.CompanyCd
AND b.ProductSalesCd = e.ProductSalesCd
LEFT JOIN coUOM i -- PK = UOMId
ON h.UOMId = i.UOMId
INNER JOIN coProductOldInformation j -- PK = CompanyCd, BFStatus, SpecCd
ON a.CompanyCd = j.CompanyCd
AND b.BFStatus = j.BFStatus
AND b.ProductSalesCd = j.ProductSalesCd
INNER JOIN coProductGroup1 g1 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup1Cd
ON e.ProductGroup1Cd = g1.ProductGroup1Cd
INNER JOIN coProductGroup2 g2 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup2Cd
ON e.ProductGroup1Cd = g2.ProductGroup1Cd
解決方法は?
A
LEFT JOIN
よりも絶対に速くありません。
INNER JOIN
. 実際、より遅いです。定義によれば、外部結合(
LEFT JOIN
または
RIGHT JOIN
のすべての作業を行わなければなりません。
INNER JOIN
さらに、結果をヌル拡張する余分な作業もあります。 また、より多くの行を返すことが予想され、結果セットのサイズが大きくなるため、単純に実行時間の合計がさらに増加します。
(また、仮に
LEFT JOIN
だった
で速くなった。
特定
とは機能的に同等ではありません。
INNER JOIN
そのため、単純に一方のインスタンスをすべて他方のインスタンスに置き換えることはできません!)
ほとんどの場合、パフォーマンスの問題は、候補キーまたは外部キーが適切にインデックスされていないなど、他の場所にあります。 9つのテーブルを結合するのは非常に多いので、速度低下の原因は文字通りほとんどどこにでもあり得ます。 スキーマを投稿していただければ、より詳細な情報を提供できるかもしれません。
編集する
このことをさらに振り返ると、ある状況下で
LEFT JOIN
よりも速いかもしれません。
INNER JOIN
というときです。
- 一部のテーブルは 大変 小さい(例えば、10行以下)。
- テーブルには、クエリをカバーするのに十分なインデックスがありません。
この例で考えてみましょう。
CREATE TABLE #Test1
(
ID int NOT NULL PRIMARY KEY,
Name varchar(50) NOT NULL
)
INSERT #Test1 (ID, Name) VALUES (1, 'One')
INSERT #Test1 (ID, Name) VALUES (2, 'Two')
INSERT #Test1 (ID, Name) VALUES (3, 'Three')
INSERT #Test1 (ID, Name) VALUES (4, 'Four')
INSERT #Test1 (ID, Name) VALUES (5, 'Five')
CREATE TABLE #Test2
(
ID int NOT NULL PRIMARY KEY,
Name varchar(50) NOT NULL
)
INSERT #Test2 (ID, Name) VALUES (1, 'One')
INSERT #Test2 (ID, Name) VALUES (2, 'Two')
INSERT #Test2 (ID, Name) VALUES (3, 'Three')
INSERT #Test2 (ID, Name) VALUES (4, 'Four')
INSERT #Test2 (ID, Name) VALUES (5, 'Five')
SELECT *
FROM #Test1 t1
INNER JOIN #Test2 t2
ON t2.Name = t1.Name
SELECT *
FROM #Test1 t1
LEFT JOIN #Test2 t2
ON t2.Name = t1.Name
DROP TABLE #Test1
DROP TABLE #Test2
これを実行して実行プランを表示すると
INNER JOIN
クエリの方が
LEFT JOIN
というのは、上記の2つの条件を満たしているからです。 それは、SQL Server が
INNER JOIN
に対してネストされたループを実行します。
LEFT JOIN
前者は
通常
よりもはるかに高速ですが、行数が非常に少ないため
と
インデックスを使用しないため、ハッシュ処理がクエリの中で最も高価な部分となります。
好きなプログラミング言語で、5つの要素を持つリストと5つの要素を持つハッシュテーブルを大量に検索するプログラムを書けば、同じ効果を確認することができます。 サイズが小さいので、実際にはハッシュテーブルの方が遅くなります。 しかし、50要素、5000要素と増やすと、ハッシュテーブルのO(1)に対し、リストのO(N)となり、遅くなるのである。
しかし、このクエリを
ID
カラムではなく
Name
をクリックすると、まったく違うことがわかります。 この場合、両方のクエリでネストされたループが行われます。
INNER JOIN
バージョンでは、クラスタ化されたインデックススキャンのひとつをシークに置き換えることができるため、文字通り
桁違いの
行数が多い場合、より高速になります。
つまり、結論としては、ほぼ間違いなくインデックスまたはインデックスカバレッジの問題で、おそらく1つまたは複数の非常に小さなテーブルと組み合わさっているのです。 このような状況でSQL Server
可能性があります。
に対して、より悪い実行計画を選択することがあります。
INNER JOIN
よりも
LEFT JOIN
.
関連
-
[解決済み] FROM のサブクエリにはエイリアスが必要です。
-
[解決済み] SQL ServerでSELECTからUPDATEする方法とは?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] SQL ServerにおけるLEFT JOINとLEFT OUTER JOINの比較
-
[解決済み] SQL ServerでJOINを使用してUPDATE文を実行するにはどうすればよいですか?
-
[解決済み] JOINとINNER JOINの違いについて
-
[解決済み】「INNER JOIN」と「OUTER JOIN」の違いは何ですか?
-
[解決済み】SQL Serverで既存のテーブルにデフォルト値を持つカラムを追加する
-
[解決済み] SQL ServerでINNER JOINを使用して削除するにはどうすればよいですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 列名または提供された値の数がテーブル定義と一致しない
-
[解決済み】データベースへの「ネイティブ」SQL接続を使用するとはどういう意味ですか?
-
[解決済み】SQL ServerでIdentityカラムを更新する方法は?
-
[解決済み】SQL Server: 無効なカラム名
-
[解決済み】SQL Serverは「集約関数やサブクエリを含む式に対して集約関数を実行できない」が、Sybaseはできる。
-
[解決済み] pg_restoreです。[archiver] 入力ファイルはテキスト形式のダンプであるように見えます。psql を使用してください。
-
[解決済み] SELECT DISTINCTを指定した場合、ORDER BY項目は必ず選択リストに表示されます。
-
[解決済み] FROM のサブクエリにはエイリアスが必要です。
-
[解決済み] 1行目4列目(年)の一括読み込みデータ変換エラー(型の不一致または指定したコードページに対して無効な文字)
-
[解決済み] 外部キーはクエリーのパフォーマンスを向上させるか?