Yorumlarda zaten belirtildiği gibi, istatistiklerinizi güncellemeniz gerekiyor gibi görünüyor.
Çıkan satır tahmini sayısı arasındaki katılmak location
ve testruns
iki planları arasındaki derece farklıdır.
Plan tahminlerine katıl: 1
Alt sorgu planı tahminleri: 8.748
Birleşmeden çıkan gerçek satır sayısı 14.276'dır.
Tabii ki, birleştirme sürümünün 3 satırın gelip location
tek bir birleştirilmiş satır üretmesi gerektiğini tahmin etmesi sezgisel bir anlam ifade etmiyor, ancak alt sorgu bu satırlardan birinin aynı birleştirmeden 8.748 üreteceğini tahmin ediyor, ancak yine de başardım bunu yeniden üretmek için.
İstatistikler oluşturulduğunda histogramlar arasında çaprazlama yoksa bu gerçekleşir. Birleştirme sürümü tek bir satır olduğunu varsayar. Ve alt sorgunun tek eşitlik arayışı, bilinmeyen bir değişkene karşı eşitlik arayışı ile aynı tahmini satırları varsayar.
Testrunlarının asıl özelliği 26244
. Üç ayrı konum kimliği ile doldurulduğu varsayılırsa, aşağıdaki sorgu 8,748
satırların döndürüleceğini tahmin eder ( 26244/3
)
declare @i int
SELECT *
FROM testruns AS tr
WHERE tr.location_id = @i
Tablonun locations
yalnızca 3 satır içerdiği göz önüne alındığında , istatistiklerin oluşturulduğu bir durumu gerçekleştirmek kolaydır (daha sonra yabancı anahtar kabul etmezsek) ve ardından veriler, döndürülen gerçek satır sayısını önemli ölçüde etkileyecek şekilde değiştirilir, ancak otomatik istatistik güncellemelerini açma ve eşiği yeniden derleme.
SQL Server, bu birleştirmeden çıkan satırların sayısını o kadar yanlış alırsa, birleştirme planındaki diğer tüm satır tahminleri büyük ölçüde küçümsenir. Bunun yanı sıra bir seri plan almak anlamına da sorgu yetersiz bir bellek hibe alır ve tür ve karma birleşmeleri dökülme tempdb
.
Planınızda gösterilen gerçek ve tahmini satırları yeniden üreten olası bir senaryo aşağıdadır.
CREATE TABLE location
(
id INT CONSTRAINT locationpk PRIMARY KEY,
location VARCHAR(MAX) /*From the separate filter think you are using max?*/
)
/*Temporary ids these will be updated later*/
INSERT INTO location
VALUES (101, 'Coventry'),
(102, 'Nottingham'),
(103, 'Derby')
CREATE TABLE testruns
(
location_id INT
)
CREATE CLUSTERED INDEX IX ON testruns(location_id)
/*Add in 26244 rows of data split over three ids*/
INSERT INTO testruns
SELECT TOP (5984) 1
FROM master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (5984) 2
FROM master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (14276) 3
FROM master..spt_values v1, master..spt_values v2
/*Create statistics. The location_id histograms don't intersect at all*/
UPDATE STATISTICS location(locationpk) WITH FULLSCAN;
UPDATE STATISTICS testruns(IX) WITH FULLSCAN;
/* UPDATE location.id. Three row update is below recompile threshold*/
UPDATE location
SET id = id - 100
Ardından, aşağıdaki sorguları çalıştırmak aynı tahmini ve gerçek tutarsızlığı verir
SELECT *
FROM testruns AS tr
WHERE tr.location_id = (SELECT id
FROM location
WHERE location = 'Derby')
SELECT *
FROM testruns AS tr
JOIN location loc
ON tr.location_id = loc.id
WHERE loc.location = ( 'Derby' )