Kum torbası
Top Quality Blog Posts® üzerinde çalışırken, gerçekten çıldırtıcı bulduğum bazı optimize edici davranışlarla karşılaştım . Hemen bir açıklamam yok, en azından memnun değilim, bu yüzden akıllı birinin ortaya çıkması durumunda buraya koyuyorum.
Takip etmek isterseniz, Yığın Taşması veri dökümünün 2013 sürümünü buradan alabilirsiniz . Bir ek dizin ile Yorumlar tablosunu kullanıyorum.
CREATE INDEX [ix_ennui] ON [dbo].[Comments] ( [UserId], [Score] DESC );
Birinci Sorgu
Tabloyu böyle sorguladığımda garip bir sorgu planı alıyorum .
WITH x
AS
(
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score DESC
)
SELECT *
FROM x
WHERE x.Score >= 500;
Skor SARGable tahmini CTE içine itilmez. Planın çok ilerisinde bir filtre operatörü var.
Garip bulduğumdan beri ORDER BY
filtre ile aynı sütunda.
İki Sorgu
Sorguyu değiştirirsem, itilir.
WITH x
AS
(
SELECT c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
)
SELECT TOP 101 *
FROM x
WHERE x.Score >= 500
ORDER BY x.Score DESC;
Sorgu planı değişikliği de ve diske hiçbir sızıntının ile çok daha hızlı çalışır. Her ikisi de aynı sonuçları üretir ve kümelenmemiş indeks taramasındaki yüklem.
Üç Sorgu
Bu, sorguyu şöyle yazmanın eşdeğeridir:
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
WHERE c.Score >= 500
ORDER BY c.Score DESC;
Dört Sorgu
Türetilmiş bir tablo kullanıldığında, ilk CTE sorgusuyla aynı "hatalı" sorgu planı elde edilir
SELECT *
FROM ( SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score DESC ) AS x
WHERE x.Score >= 500;
İşler tuhaflaştığında ...
Ben artan veri ve filtre için sorgu değiştirmek <=
.
Bu soruyu uzun süre sormamak için, her şeyi bir araya getireceğim.
Sorguları
--Derived table
SELECT *
FROM ( SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score ASC ) AS x
WHERE x.Score <= 500;
--TOP inside CTE
WITH x
AS
(
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score ASC
)
SELECT *
FROM x
WHERE x.Score <= 500;
--Written normally
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
WHERE c.Score <= 500
ORDER BY c.Score ASC;
--TOP outside CTE
WITH x
AS
(
SELECT c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
)
SELECT TOP 101 *
FROM x
WHERE x.Score <= 500
ORDER BY x.Score ASC;
Planlar
Bu sorguların hiçbirinin kümelenmemiş dizinden faydalanmadığını unutmayın - burada değişen tek şey filtre operatörünün konumu. Hiçbir durumda yüklem dizin erişimine aktarılmaz.
Bir Soru Görünüyor!
SARGable yükleminin diğerlerinde değil bazı senaryolarda itilebilmesinin bir nedeni var mı? Sorgularda azalan düzende sıralanan farklar ilginçtir, ancak bunlar ve artan tuhaf olanlar arasındaki farklar.
İlgilenen herkes için, sadece bir endeksi olan planlar şunlardır Score
: