SARGable tahminleri ne zaman bir CTE veya türetilmiş tabloya aktarılabilir?


15

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;

FINDIK

Skor SARGable tahmini CTE içine itilmez. Planın çok ilerisinde bir filtre operatörü var.

FINDIK

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.

FINDIK

FINDIK

Üç 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

Bağlantı planla .

FINDIK

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:

Yanıtlar:


11

Burada oyunda birkaç sorun var.

İtme geçmişi tahmin eder TOP

Optimize edici, TOPgüvenli bir şekilde yapılabileceği sınırlı durumlarda bile, şu anda a geçmişini zorlayamaz *. Bu sınırlama, yüklemin .'den daha yüksek bir kapsamda olduğu sorudaki tüm sorguların davranışını açıklar TOP.

Geçici çözüm yeniden yazma işlemini el ile yapmaktır. Temel sorun, tahminleri bir pencere fonksiyonunun ötesine itme örneğine benzer , ancak aşağıdaki gibi karşılık gelen özel bir kural yokturSelOnSeqPrj .

Benim kişisel fikrim, SelOnTopinsanlar TOPbir tür 'optimizasyon çiti' sağlamak için kasıtlı olarak sorgu yazdıkları için benzeri olmayan bir arama kuralının uygulanmadığıdır .

* Bu, yüklemin ilgili ORDER BYmaddede yer alması gerektiği anlamına gelir ve TOPherhangi bir eşitsizliğin yönü, sıralama yönüne uygun olmalıdır. Dönüşümün SQL Server'daki NULL'ların sıralama davranışını da hesaba katması gerekir. Genel olarak, sınırlamalar muhtemelen bu dönüşümün pratikte ek keşif çabalarını haklı çıkarmak için yeterince yararlı olmayacağı anlamına gelmektedir.

Maliyetleme sorunları

Soruda kalan yürütme planları, Scoresütundaki değerlerin dağılımı (satır sayısı <= 500> = 500) ve satır hedefinin etkisi nedeniyle maliyete dayalı seçenekler olarak açıklanabilir getirdiği .TOP .

Örneğin, sorgu:

--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;

... bir Filtrede görünüşte baskısız bir yüklemi olan bir plan üretir:

satır hedefi nedeniyle geç filtre

Sıralamanın 101 satır ürettiği tahmin edilmektedir. Bu, Üst tarafından eklenen satır hedefinin etkisidir. Bu, Sırala ve Filtrele'nin tahmini maliyetini, bunun daha ucuz bir seçenek gibi görünmesini sağlayacak kadar etkiler. Bu planın tahmini maliyeti 2401,39 birimdir.

Bir sorgu ipucu ile satır hedeflerini devre dışı bırakırsak:

--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
OPTION (USE HINT ('DISABLE_OPTIMIZER_ROWGOAL'));

... üretilen yürütme planı:

sıra hedefi olmayan plan

Yüklem, geriye eğilemez bir yüklem olarak taranmaya itilmiştir ve tüm planın maliyeti 2402.32 birimdir.

<= 500Yüklemenin herhangi bir satırı filtrelemesinin beklenmediğine dikkat edin . Örneğin, daha küçük bir sayı seçmiş <= 50olsaydınız, optimize edici, satır hedefi efektinden bağımsız olarak push-predicate planını tercih ederdi.

İle sorguda Score DESCve Score >= 500yüklemi:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score >= 500
ORDER BY
    c.Score DESC;

Şimdi yüklemin çok seçici olması bekleniyor, bu nedenle optimizatör yüklemi zorlamayı ve aramalarla kümelenmemiş dizini kullanmayı seçiyor :

seçici yüklem

Yine, optimizer birden fazla alternatifi düşündü ve bunu her zamanki gibi en ucuz seçenek olarak seçti.

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.