Alt sorgu neden paralelliği kullanıyor ve birleştirme kullanmıyor?


16

SQL Server, bir alt sorgu kullanan ancak bir birleştirmeyi kullanırken bu sorguyu çalıştırırken neden paralellik kullanıyor? Birleştirme sürümü seri olarak çalışır ve tamamlanması yaklaşık 30 kat daha uzun sürer.

Sürüme katıl: ~ 30secs

resim açıklamasını buraya girin

Alt sorgu sürümü: <1second

resim açıklamasını buraya girin

EDIT: Sorgu planının Xml sürümleri:

Sürüme KATIL

SUBQUERY sürümü

Yanıtlar:


12

Yorumlarda zaten belirtildiği gibi, istatistiklerinizi güncellemeniz gerekiyor gibi görünüyor.

Çıkan satır tahmini sayısı arasındaki katılmak locationve testrunsiki planları arasındaki derece farklıdır.

Plan tahminlerine katıl: 1

Plan 1

Alt sorgu planı tahminleri: 8.748

resim açıklamasını buraya girin

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 locationtek 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,748satı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 locationsyalnı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' ) 

Konuma benzersiz bir kısıtlama eklenirse, "=" ifadesinin tam olarak bir satır döndüreceği açıkça görülür. Daha sonra örneğinizde sorgu planları özdeşleşir (taramalar -> arar): tabloyu değiştir Konum ekle kısıtlama U_Location_Location unique kümelenmemiş (Konum);
crokusek

@crokusek evet. Daha sonra ne demek istediğini anladım ve yorumumu sildim! Bu, birleştirme sürümü için tahmin edilen satır sayısını alt sorgu ile aynı olacak şekilde artırıyor mu? Test etmek için şu anda PC'de değil misiniz?
Martin Smith

@crokusek Yep. bu singleton durumundaki alt sorgu için birleşimin dışındaki tahmini satırlara benzer.
Martin Smith

Evet. Aynı sorgu planı, her ikisi de 8748, her iki gerçek 14276 tahmin. Btw, locationId önceden hesaplamak bu farkı çözeceğini düşündüm ama değil.
crokusek

1
@crokusek - DB'm içinde yer ve benzeri yerlere benzersiz bir kısıtlama da ekleyeceğim. Etkilenen sorgu optimizasyonu fark etmedi itiraf etmeliyim. Sadece veri bütünlüğünü sağlamak olduğunu düşündüm. Bu soruya katıldığınız için teşekkür ederiz.
Chris L
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.