Bu 2 sorguyu karşılaştırın. Filtreyi birleştirme ölçütlerine veya daha önceki cümlelere koymak daha mı hızlıdır? Sonuç kümesini mümkün olan en kısa sürede azalttığından, her zaman katılma ölçütlerinde daha hızlı olduğunu hissettim, ancak kesin olarak bilmiyorum.Hangi SQL sorgusu daha hızlıdır? Katılma ölçütlerine göre filtreleme ya da nerede yan tümce?
Görmek için bazı testler yapacağım, ama aynı zamanda okumak için daha net olan fikirleri de almak istedim.
Sorgu 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? */
Sorgu 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
DÜZENLEME Bazı testler yaptım ve sonuç aslında çok yakın olduğunu gösteriyor ama
WHERE
yan tümcesi gerçekten kaygandır tly daha hızlı! =)
Filtrenin WHERE
maddesine uygulanmasının daha mantıklı olduğuna kesinlikle katılıyorum, yalnızca performans açısından merak ettim.
KRİTERLER ELAPSED ZAMAN: 143.016 msn
ELAPSED ZAMAN KRİTERLERİ JOIN: 143.256 msn
TEST
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
Verilere bağlı olarak, WHERE ve JOIN ölçütleri farklı sonuçlar getirebilir. –
@OMG Ponies çok doğru, ama çoğu kez de değil. –
Farklılık olarak 5 farkı fark etmeyeceğim, fark olarak aynıdır. % 2'lik bir fark için önem kazanmak istersiniz. Sadece rastgele olmadığından emin olmak için testleri 1000 kez daha iyi çalıştırın. – TomTom