Bunun neden IF EXISTS
bu kadar uzun sürdüğünü ve bu kadar çok okuma yaptığını bilen bir fikrin var mı? Ayrıca select deyimini yapmak için değiştirdim ve SELECT TOP 1 [dlc].[id]
2 dakika sonra öldürdüm.
Bu soruya cevabımda açıkladığım gibi:
TOP bir uygulama planını nasıl (ve neden) etkiler?
Kullanımı EXISTS
, en iyi duruma getiricinin ilk sırayı hızlıca bulmayı amaçlayan bir yürütme planı hazırladığı bir satır hedefi sunar. Bunu yaparken, verilerin eşit şekilde dağıldığını varsaymaktadır. Örneğin, istatistikler 100.000 satırda beklenen 100 eşleşme olduğunu gösteriyorsa, ilk eşleşmeyi bulmak için yalnızca 1000 satır okumak zorunda kalacağını varsayacaktır.
Bu varsayımın hatalı olduğu ortaya çıkarsa, beklenenden daha uzun yürütme süresine neden olur. Örneğin, SQL Server aramada çok geçe ilk eşleme değerini bulmak için gerçekleşen bir erişim yöntemi (örn. Sırasız tarama) seçerse, neredeyse tamamen taramayla sonuçlanabilir. Öte yandan, ilk birkaç satır arasında eşleşen bir satır bulunursa, performans çok iyi olacaktır. Bu, sıralı hedeflerle temel risk - tutarsız performans.
Geçici bir düzeltme olarak, bir sayı (*) yapmak ve bu değeri bir değişkene atamak için değiştirdim.
Sorguyu, satır hedefi atanmayacak şekilde yeniden düzenlemek genellikle mümkündür. Satır hedefi olmadan, ilk eşleşen satırla karşılaşıldığında (doğru yazılırsa) sorgu hala sona erebilir, ancak yürütme planı stratejisinin farklı olması (ve umarım daha etkili) olması olasıdır. Açıkçası, count (*) tüm satırları okumayı gerektirir, bu yüzden mükemmel bir alternatif değildir.
SQL Server 2008 R2 veya sonraki bir sürümünü kullanıyorsanız, genel olarak belgelenmemiş ve desteklenmeyen izleme bayrağı 4138'i , bir satır hedefi olmadan bir yürütme planı almak için de kullanabilirsiniz . Bu bayrak, desteklenen bir ipucu kullanılarak da belirtilebilir OPTION (QUERYTRACEON 4138)
, ancak bir plan kılavuzunda kullanılmadıkça çalışma zamanı sysadmin izni gerektirdiğini unutmayın .
ne yazık ki
Yukarıdakilerin hiçbiri IF EXISTS
koşullu bir ifade ile işlevsel değildir . Sadece normal DML için geçerlidir. O edecek alternatif çalışmak SELECT TOP (1)
denedin formülasyon. Bu, daha COUNT(*)
önce belirtildiği gibi tüm nitelikli satırları sayması gereken kullanmaktan daha iyi olabilir .
Bununla birlikte, aramayı erken sona erdirirken, satır hedefinden kaçınmanıza veya kontrol etmenize olanak sağlayacak olan bu gereksinimi ifade etmenin birçok yolu vardır. Son bir örnek:
DECLARE @Exists bit;
SELECT @Exists =
CASE
WHEN EXISTS
(
SELECT [dlc].[ID]
FROM TableDLC [dlc]
JOIN TableD [d]
ON [d].[ID] = [dlc].[ID]
JOIN TableC [c]
ON [c].[ID] = [d].[ID2]
WHERE [c].[Name] <> [dlc].[Name]
)
THEN CONVERT(bit, 1)
ELSE CONVERT(bit, 0)
END
OPTION (QUERYTRACEON 4138);
IF @Exists = 1
BEGIN
...
END;
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
.