Bir kaynak tablodan yalnızca hedef tabloda yoksa satır ekleyen aşağıdaki sorguyu göz önünde bulundurun:
INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
SELECT 1
FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);
Olası bir plan şekli bir birleştirme birleşimi ve istekli bir makara içerir. İstekli biriktirme operatörü Cadılar Bayramı Sorununu çözmek için hazır :
Makinemde yukarıdaki kod yaklaşık 6900 ms'de çalışıyor. Tabloları oluşturmak için repro kodu sorunun altında yer almaktadır. Performanstan memnun kalmazsam, istekli makaraya güvenmek yerine geçici bir tabloya eklenecek satırları yüklemeyi deneyebilirim. İşte olası bir uygulama:
DROP TABLE IF EXISTS #CONSULTANT_RECOMMENDED_TEMP_TABLE;
CREATE TABLE #CONSULTANT_RECOMMENDED_TEMP_TABLE (
ID BIGINT,
PRIMARY KEY (ID)
);
INSERT INTO #CONSULTANT_RECOMMENDED_TEMP_TABLE WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
SELECT 1
FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);
INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT new_rows.ID
FROM #CONSULTANT_RECOMMENDED_TEMP_TABLE new_rows
OPTION (MAXDOP 1);
Yeni kod yaklaşık 4400 ms'de yürütülür. Gerçek planları alabilir ve operatör düzeyinde zamanın nerede harcandığını incelemek için Gerçek Zaman İstatistikleri ™ 'ni kullanabilirim. Gerçek bir plan istemenin, toplamlar önceki sonuçlarla eşleşmemesi için bu sorgular için önemli bir ek yük getirdiğini unutmayın.
╔═════════════╦═════════════╦══════════════╗
║ operator ║ first query ║ second query ║
╠═════════════╬═════════════╬══════════════╣
║ big scan ║ 1771 ║ 1744 ║
║ little scan ║ 163 ║ 166 ║
║ sort ║ 531 ║ 530 ║
║ merge join ║ 709 ║ 669 ║
║ spool ║ 3202 ║ N/A ║
║ temp insert ║ N/A ║ 422 ║
║ temp scan ║ N/A ║ 187 ║
║ insert ║ 3122 ║ 1545 ║
╚═════════════╩═════════════╩══════════════╝
İstekli makaralı sorgu planı, geçici tablo kullanan plana kıyasla kesici uç ve makara operatörleri üzerinde önemli ölçüde daha fazla zaman harcıyor gibi görünüyor.
Geçici tabloya sahip plan neden daha verimli? Istekli bir makara zaten sadece bir iç sıcaklık tablo değil mi? İçerilere odaklanan cevaplar aradığımı düşünüyorum. Çağrı yığınlarının nasıl farklı olduğunu görebiliyorum ancak büyük resmi anlayamıyorum.
Birisi bilmek istediği takdirde SQL Server 2017 CU 11 kullanıyorum. Yukarıdaki sorgularda kullanılan tabloları doldurmak için kod:
DROP TABLE IF EXISTS dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR;
CREATE TABLE dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR (
ID BIGINT NOT NULL,
PRIMARY KEY (ID)
);
INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT TOP (20000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
CROSS JOIN master..spt_values t3
OPTION (MAXDOP 1);
DROP TABLE IF EXISTS dbo.A_HEAP_OF_MOSTLY_NEW_ROWS;
CREATE TABLE dbo.A_HEAP_OF_MOSTLY_NEW_ROWS (
ID BIGINT NOT NULL
);
INSERT INTO dbo.A_HEAP_OF_MOSTLY_NEW_ROWS WITH (TABLOCK)
SELECT TOP (1900000) 19999999 + ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;