Sorgu
SELECT SUM(Amount) AS SummaryTotal
FROM PDetail WITH(NOLOCK)
WHERE ClientID = @merchid
AND PostedDate BETWEEN @datebegin AND @dateend
Tablo 103.129.000 satır içeriyor.
Hızlı plan, ClientId tarafından tarihte artık bir tahminde bulunur, ancak almak için 96 arama yapılması gerekir Amount
. <ParameterList>
Şöyle planında bölümdür.
<ParameterList>
<ColumnReference Column="@dateend"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@datebegin"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@merchid"
ParameterRuntimeValue="(78155)" />
</ParameterList>
Yavaş plan tarihe göre bakar ve İstemci Kimliği üzerindeki kalıntı yüklemeyi değerlendirmek ve tutarı almak için arama yapar (Tahmini 1 - Gerçek 7,388,383). <ParameterList>
bölümdür
<ParameterList>
<ColumnReference Column="@EndDate"
ParameterCompiledValue="'2013-02-01 23:59:00.000'"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@BeginDate"
ParameterCompiledValue="'2013-01-01 00:00:00.000'"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@ClientID"
ParameterCompiledValue="(78155)"
ParameterRuntimeValue="(78155)" />
</ParameterList>
Bu ikinci durumda ParameterCompiledValue
ise değil boş. SQL Server, sorguda kullanılan değerleri başarıyla kokladı.
"SQL Server 2005 Pratik Sorun Giderme" kitabında yerel değişkenlerin kullanımı hakkında söylenecek söz var.
Parametre koklamayı engellemek için yerel değişkenleri kullanmak oldukça yaygın bir hiledir, ancak OPTION (RECOMPILE)
ve OPTION (OPTIMIZE FOR)
ipuçları… genellikle daha zarif ve biraz daha az riskli çözümlerdir.
Not
SQL Server 2005'te, ifade seviyesi derlemesi, sorgunun ilk yürütülmesinden hemen öncesine kadar ertelenecek olan saklı yordamdaki tek bir ifadenin derlenmesine izin verir. O zamana kadar yerel değişkenin değeri bilinirdi. Teorik olarak SQL Server, yerel değişken değerlerini parametreleri koklamakla aynı şekilde çekmek için bundan yararlanabilir. Ancak, SQL Server 7.0 ve SQL Server 2000+ 'de parametre koklama özelliğini engellemek için yerel değişkenlerin kullanılması yaygın olduğundan, yerel değişkenlerin koklaması SQL Server 2005'te etkinleştirilmemiştir. Gelecekteki bir SQL Server sürümünde etkin olabilir. Bir seçeneğiniz varsa, bu bölümde belirtilen diğer seçeneklerden birini kullanmanızın nedeni.
Hızlı bir testten bu sona kadar yukarıda açıklanan davranış hala 2008 ve 2012'de aynıdır ve ertelenmiş derlemeler için değişkenler koklanmamaktadır, ancak sadece açık bir OPTION RECOMPILE
ipucu kullanıldığında.
DECLARE @N INT = 0
CREATE TABLE #T ( I INT );
/*Reference to #T means this statement is subject to deferred compile*/
SELECT *
FROM master..spt_values
WHERE number = @N
AND EXISTS(SELECT COUNT(*) FROM #T)
SELECT *
FROM master..spt_values
WHERE number = @N
OPTION (RECOMPILE)
DROP TABLE #T
Ertelenmiş derlemeye rağmen, değişken koklamaz ve tahmini satır sayısı yanlış
Dolayısıyla yavaş planın, sorgunun parametrelenmiş bir versiyonuyla ilgili olduğunu varsayıyorum.
Bu ParameterCompiledValue
, ParameterRuntimeValue
tüm parametrelere eşittir, bu nedenle tipik bir parametre koklama değildir (plan bir değer kümesi için derlenmiştir, sonra başka bir değer kümesi için çalıştırılır).
Sorun, doğru parametre değerleri için derlenen planın uygunsuz olmasıdır.
Burada ve burada açıklanan yükselen tarihlerle konuya ulaşmanız muhtemeldir . 100 milyon satırlık bir tablo için, SQL Server'ın istatistikleri sizin için otomatik olarak güncellemesinden önce 20 milyonu eklemeniz (veya başka şekilde değiştirmeniz) gerekir. Görünüşe göre, en son sıfır satır güncellendiğinde, sorgudaki tarih aralığıyla eşleşti ancak şimdi 7 milyon kişi var.
Daha sık istatistik güncellemeleri planlayabilir, izleme bayraklarını göz önünde bulundurabilir 2389 - 90
veya kullanabilirsiniz; OPTIMIZE FOR UKNOWN
böylece, datetime
sütunda şu anda yanıltıcı istatistikleri kullanabilmek yerine, tahminlerde geri dönersiniz .
Bu, SQL Server'ın bir sonraki sürümünde gerekli olmayabilir (2012'den sonra). Bir ilişkili Bağlan öğesi ilginç yanıtını içeren
Microsoft tarafından 28.08.2012 tarihinde saat 13: 35'de gönderildi.
Bir sonraki önemli sürüm için bu durumu düzelten bir önemlilik tahmini geliştirmesi yaptık. Önizlememiz çıktığında ayrıntılar için bizi izlemeye devam edin. Eric
Bu 2014 gelişimine, makalenin sonuna doğru Benjamin Nevarez tarafından bakıldı:
Yeni SQL Server Kardinalite Tahmincisine İlk Bakış .
Yeni kardinalite tahmincisinin geri çekileceği ve bu durumda 1 satır tahminini vermek yerine ortalama yoğunluğu kullanacağı görülüyor.
2014 kardinalite tahmincisi ve artan anahtar sorun hakkında bazı ek ayrıntılar burada:
SQL Server 2014'te yeni işlevler - Bölüm 2 - Yeni Kardinalite Tahmini