[解決済み] SQLクエリはどちらが速いか?Join条件によるフィルタリングかWhere句によるフィルタリングか?
2022-10-30 02:43:28
質問
これらの2つのクエリを比較してください。フィルタを結合基準に置く方が速いですか?
WHERE
節に置く方が速いです。私は、可能な限り早い段階で結果セットを減らすことができるため、結合条件の方が速いと感じていましたが、確かなことはわかりません。
これからいくつかテストを作って見ようと思いますが、どちらが読みやすいかについても意見を聞きたいと思いました。
クエリ1
SELECT *
FROM TableA a
INNER JOIN TableXRef x
ON a.ID = x.TableAID
INNER JOIN TableB b
ON x.TableBID = b.ID
WHERE a.ID = 1 /* <-- Filter here? */
クエリ2
SELECT *
FROM TableA a
INNER JOIN TableXRef x
ON a.ID = x.TableAID
AND a.ID = 1 /* <-- Or filter here? */
INNER JOIN TableB b
ON x.TableBID = b.ID
EDIT
いくつかテストをしてみたところ、実際には非常に近い結果になっていますが
WHERE
節は実際にはわずかに高速です! =)
のフィルタを適用するのがより理にかなっているということに、私はまったく同意します。
WHERE
節にフィルタを適用する方が理にかなっていることにまったく同意しますが、パフォーマンスへの影響について知りたかっただけです。
elapsed time where criteria:
143016ミリ秒
経過時間の結合条件です。
143256ミリ秒
テスト
SET NOCOUNT ON;
DECLARE @num INT,
@iter INT
SELECT @num = 1000, -- Number of records in TableA and TableB, the cross table is populated with a CROSS JOIN from A to B
@iter = 1000 -- Number of select iterations to perform
DECLARE @a TABLE (
id INT
)
DECLARE @b TABLE (
id INT
)
DECLARE @x TABLE (
aid INT,
bid INT
)
DECLARE @num_curr INT
SELECT @num_curr = 1
WHILE (@num_curr <= @num)
BEGIN
INSERT @a (id) SELECT @num_curr
INSERT @b (id) SELECT @num_curr
SELECT @num_curr = @num_curr + 1
END
INSERT @x (aid, bid)
SELECT a.id,
b.id
FROM @a a
CROSS JOIN @b b
/*
TEST
*/
DECLARE @begin_where DATETIME,
@end_where DATETIME,
@count_where INT,
@begin_join DATETIME,
@end_join DATETIME,
@count_join INT,
@curr INT,
@aid INT
DECLARE @temp TABLE (
curr INT,
aid INT,
bid INT
)
DELETE FROM @temp
SELECT @curr = 0,
@aid = 50
SELECT @begin_where = CURRENT_TIMESTAMP
WHILE (@curr < @iter)
BEGIN
INSERT @temp (curr, aid, bid)
SELECT @curr,
aid,
bid
FROM @a a
INNER JOIN @x x
ON a.id = x.aid
INNER JOIN @b b
ON x.bid = b.id
WHERE a.id = @aid
SELECT @curr = @curr + 1
END
SELECT @end_where = CURRENT_TIMESTAMP
SELECT @count_where = COUNT(1) FROM @temp
DELETE FROM @temp
SELECT @curr = 0
SELECT @begin_join = CURRENT_TIMESTAMP
WHILE (@curr < @iter)
BEGIN
INSERT @temp (curr, aid, bid)
SELECT @curr,
aid,
bid
FROM @a a
INNER JOIN @x x
ON a.id = x.aid
AND a.id = @aid
INNER JOIN @b b
ON x.bid = b.id
SELECT @curr = @curr + 1
END
SELECT @end_join = CURRENT_TIMESTAMP
SELECT @count_join = COUNT(1) FROM @temp
DELETE FROM @temp
SELECT @count_where AS count_where,
@count_join AS count_join,
DATEDIFF(millisecond, @begin_where, @end_where) AS elapsed_where,
DATEDIFF(millisecond, @begin_join, @end_join) AS elapsed_join
どのように解決するのですか?
パフォーマンス的には同じです(同じプランを作成します)。
論理的には、以下のように置き換えてもまだ意味のある操作をする必要があります。
INNER JOIN
を
LEFT JOIN
.
あなたのまさにその場合、これは次のようになります。
SELECT *
FROM TableA a
LEFT JOIN
TableXRef x
ON x.TableAID = a.ID
AND a.ID = 1
LEFT JOIN
TableB b
ON x.TableBID = b.ID
またはこれ
SELECT *
FROM TableA a
LEFT JOIN
TableXRef x
ON x.TableAID = a.ID
LEFT JOIN
TableB b
ON b.id = x.TableBID
WHERE a.id = 1
前者のクエリは
a.id
以外の
1
であるため、後者の構文(
WHERE
のある) 後者の構文の方が論理的に一貫しています。
関連
-
[解決済み] SQLサーバーでNULL = NULLがfalseに評価される理由
-
[解決済み] SQL ServerにおけるLEFT JOINとLEFT OUTER JOINの比較
-
[解決済み] SQL ServerでJOINを使用してUPDATE文を実行するにはどうすればよいですか?
-
[解決済み] SQLのIN句をパラメータ化する
-
[解決済み] INNER JOIN ON vs WHERE句
-
[解決済み] SQL ServerでJOINを使用してテーブルを更新しますか?
-
[解決済み] SQL JOIN - WHERE句とON句の比較
-
[解決済み] SQL ServerでINNER JOINを使用して削除するにはどうすればよいですか?
-
[解決済み】ジョインとサブクエリの比較
-
[解決済み】結合を使用したSQL更新クエリ
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
MySQL - ストアドプロシージャ (データ型、関数)
-
MHAの高可用性構成とフェイルオーバー
-
windows mysql prompt access denied for user ''@'localhost' to database.
-
[解決済み] SQL Server : 列を行に変換する
-
[解決済み] SQL Serverでテーブルからカラム名を取得するにはどうすればよいですか?
-
[解決済み] 最初の行への結合方法
-
[解決済み] SQL Serverでレコードを削除した後、IDシードをリセットする。
-
[解決済み] SQL Server の VARCHAR/NVARCHAR 文字列に改行を挿入する方法
-
[解決済み] SQLでランダムな行を要求する方法は?
-
[解決済み] SQL Serverで結果をページ分割する最も良い方法は何ですか?