Aşağıdaki gibi bir sorgu var:
DELETE FROM tblFEStatsBrowsers WHERE BrowserID NOT IN (
SELECT DISTINCT BrowserID FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID IS NOT NULL
)
tblFEStatsBrowsers'in 553 satırı var.
tblFEStatsPaperHits 47.974.301 satıra sahiptir.
tblFEStatsBrowsers:
CREATE TABLE [dbo].[tblFEStatsBrowsers](
[BrowserID] [smallint] IDENTITY(1,1) NOT NULL,
[Browser] [varchar](50) NOT NULL,
[Name] [varchar](40) NOT NULL,
[Version] [varchar](10) NOT NULL,
CONSTRAINT [PK_tblFEStatsBrowsers] PRIMARY KEY CLUSTERED ([BrowserID] ASC)
)
tblFEStatsPaperHits:
CREATE TABLE [dbo].[tblFEStatsPaperHits](
[PaperID] [int] NOT NULL,
[Created] [smalldatetime] NOT NULL,
[IP] [binary](4) NULL,
[PlatformID] [tinyint] NULL,
[BrowserID] [smallint] NULL,
[ReferrerID] [int] NULL,
[UserLanguage] [char](2) NULL
)
Tarayıcı Kimliği içermeyen tblFEStatsPaperHits üzerinde kümelenmiş bir dizin var. İç sorgulama yapmak, bu nedenle tamamen tamam olan bir tblFEStatsPaperHits tablo taraması gerektirir.
Şu anda, tblFEStatsBrowsers'daki her bir satır için tam bir tarama gerçekleştiriliyor, yani 553 tblFEStatsPaperHits tam tablo taraması var.
NEREDE BİR VARLIKLARA yeniden yazmak, planı değiştirmiyor:
DELETE FROM tblFEStatsBrowsers WHERE NOT EXISTS (
SELECT * FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID = tblFEStatsBrowsers.BrowserID
)
Ancak, Adam Machanic tarafından önerildiği gibi, bir HASH JOIN seçeneği eklemek, optimum uygulama planına neden olur (sadece bir tblFEStatsPaperHits taraması):
DELETE FROM tblFEStatsBrowsers WHERE NOT EXISTS (
SELECT * FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID = tblFEStatsBrowsers.BrowserID
) OPTION (HASH JOIN)
Şimdi bu, bunun nasıl düzeltileceği ile ilgili bir soru değil - OPTION (HASH JOIN) öğesini kullanabilir veya manuel olarak geçici bir tablo oluşturabilirim. Sorgu en iyi duruma getiricinin neden şu anda yaptığı planı kullandığını merak ediyorum.
QO Tarayıcı Kimliği sütununda herhangi bir istatistik bulunmadığından, sanırım en kötü - 50 milyon farklı değer olduğunu varsayıyor, bu yüzden oldukça büyük bir bellek / tempdb çalışma masası gerektiriyor. Bu nedenle, en güvenli yol her satır için tblFEStatsBrowsers'da tarama yapmaktır. İki tablodaki BrowserID sütunları arasında yabancı anahtar ilişkisi yoktur, bu nedenle QO herhangi bir bilgiyi tblFEStatsBrowsers'dan düşemez.
Bu, sesler kadar basit mi, sebep mi?
Güncelleme 1
Birkaç istatistik vermek için: OPTION (HASH JOIN):
208.711 mantıksal okuma (12 tarama)
SEÇENEK (LOOP JOIN, HASH GROUP):
11.008.698 mantıksal okumalar (~ Tarayıcı Kimliği başına tarama (339))
Seçenek yok: 11.008.775 mantıksal okumalar (~ Tarayıcı Kimliği başına tarama (339))
Güncelleme 2
Mükemmel cevaplar, hepiniz - teşekkürler! Sadece birini seçmek zor. Martin ilk olmasına rağmen ve Remus mükemmel bir çözüm sunsa da, detaylarda zihinselleşmesi için Kivi'ye vermeliyim :)