Benzersiz bir endekste (aynı) 1000'in tahmin edilen tahmini maliyeti bu planlarda neden farklı?


27

Aşağıdaki sorgularda her iki uygulama planının da benzersiz bir endekste 1000 deneme gerçekleştireceği tahmin edilmektedir.

Arayışlar, aynı kaynak tabloda sıralı bir tarama tarafından yönlendirilir, bu nedenle aynı sırayla aynı değerleri aramaya başlamalıdır.

Her iki iç içe döngü var <NestedLoops Optimized="false" WithOrderedPrefetch="true">

Bu görevin neden ilk planda 0.172434'e, ikincide 3.01702'ye mal olduğunu bilen var mı?

(Sorunun sebebi, ilk sorgunun, görünen maliyetin çok düşük olması nedeniyle bana bir optimizasyon olarak önerilmesiydi. Aslında daha fazla iş yapıyormuş gibi görünüyor, ama ben sadece tutarsızlığı açıklamaya çalışıyorum. .)

Kurmak

CREATE TABLE dbo.Target(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);

CREATE TABLE dbo.Staging(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL); 

INSERT INTO dbo.Target
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1,  
     master..spt_values v2;

INSERT INTO dbo.Staging
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1;

Sorgu 1 "Planı yapıştır" bağlantısı

WITH T
     AS (SELECT *
         FROM   Target AS T
         WHERE  T.KeyCol IN (SELECT S.KeyCol
                             FROM   Staging AS S))
MERGE T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
  INSERT ( KeyCol, OtherCol )
  VALUES(S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
  UPDATE SET T.OtherCol = S.OtherCol;

Sorgu 2 "Planı yapıştırın" bağlantısı

MERGE Target T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
  INSERT ( KeyCol, OtherCol )
  VALUES( S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
  UPDATE SET T.OtherCol = S.OtherCol; 

Sorgu 1

Sorgu 2

Yukarıdakiler SQL Server 2014 (SP2) üzerinde test edildi (KB3171021) - 12.0.5000.0 (X64)


@Joe Obbish yorumlarda daha basit bir repro olacağına işaret ediyor

SELECT *
FROM staging AS S 
  LEFT OUTER JOIN Target AS T 
    ON T.KeyCol = S.KeyCol;

vs

SELECT *
FROM staging AS S 
  LEFT OUTER JOIN (SELECT * FROM Target) AS T 
    ON T.KeyCol = S.KeyCol;

1.000 sıra evreleme tablosu için yukarıdakilerin her ikisi de hala iç içe döngülerle aynı plan şekline ve türetilmiş masa daha ucuz görünmeyen plana sahiptir , ancak 10.000 sıra evreleme masası ve aynı hedef tablo için yukarıdaki maliyetler arasındaki fark planı değiştirir Şekil (tam tarama ve birleştirme birleşimi, pahalı maliyetlere sahip aramalardan nispeten daha çekici görünüyordu), bu maliyet farkını göstermenin sadece planları karşılaştırmayı zorlaştırmaktan başka etkileri olabilir.

görüntü tanımını buraya girin

Yanıtlar:


20

Bu görevin neden ilk planda 0.172434'e, ikincide 3.01702'ye mal olduğunu bilen var mı?

Genel olarak konuşursak, iç içe geçmiş ilmeklerin altındaki bir iç yüzey aramasının rastgele bir G / Ç paterni olduğu varsayılır. Daha sonraki erişimler için basit bir değişim temelli indirim yapılır, bu da istenen sayfanın daha önce yinelenmiş bir şekilde hafızaya alınması olasılığını hesaba katar. Bu temel değerlendirme standart (daha yüksek) maliyeti üretmektedir.

Hakkında daha az ayrıntı biliniyor olan Smart Seek Costing adlı başka bir maliyet girişi var . Tahminime göre (ve hepsi bu kadar işte) SSC'nin iç taraftaki I / O maliyetini daha ayrıntılı olarak değerlendirme girişimi, belki de yerel sipariş ve / veya getirilecek değerler aralığını göz önünde bulundurarak. Kim bilir.

Örneğin, ilk arama işlemi yalnızca istenen satırı değil, o sayfadaki tüm satırları da getirir (dizin sırasına göre). Genel erişim modeli göz önüne alındığında, 1000 sırayı 1000 ara birimine getirmek, ileriye dönük okuma ve ön tarama devre dışı bırakılmış olsa bile, yalnızca 2 fiziksel okuma gerektirir. Bu açıdan bakıldığında, varsayılan G / Ç maliyetlemesi, önemli bir fazlalığı temsil eder ve SSC'ye göre ayarlanan maliyet, gerçeğe daha yakındır.

SSC'nin, döngünün doğrudan veya daha az doğrudan bir endeks arayışı sağladığı yerlerde ve dış referansa katılmanın arama işleminin temeli olduğu durumlarda en etkili olacağını beklemek mantıklı görünüyor. Söyleyebileceğim kadarıyla, SSC uygun fiziksel işlemler için her zaman denenir, ancak çoğu zaman arama diğer işlemlerle birleşme işleminden ayrıldığında aşağı doğru bir ayar yapmaz. Basit filtreler bunun bir istisnasıdır, çünkü belki de SQL Server bunları genellikle veri erişim operatörüne itebilir. Her durumda, en iyileştirici seçimler için oldukça derin bir desteğe sahiptir.

Dış sorgulamalar için Hesaplama Skalerinin burada SSC'ye müdahale ettiği görülmesi talihsiz bir durumdur. Bilgi İşlem Skalerleri genellikle birleşme yerinin üzerine yerleştirilir, ancak bu yerlerin olduğu yerde kalmaları gerekir. Buna rağmen, çoğu normal Hesaplama Skaleri optimizasyona karşı oldukça şeffaftır, bu yüzden bu biraz şaşırtıcı.

Ne olursa olsun, fiziksel işlem PhyOp_Rangebir endekste basit bir seçimden üretildiğinde SelIdxToRng, SSC etkilidir. Daha karmaşık SelToIdxStrategy(bir tabloda bir endeks stratejisine seçim) kullanıldığında, PhyOp_Rangesonuç SSC'yi çalıştırır ancak azalmaya neden olmaz. Yine, daha basit ve daha doğrudan işlemlerin SSC ile en iyi şekilde çalıştığı görülmektedir.

Size SSC'nin tam olarak ne yaptığını söyleyebilmeyi ve tam hesaplamaları gösterebilmeyi isterdim, ancak bu ayrıntıları bilmiyorum. Kendiniz için mevcut sınırlı izleme çıktısını keşfetmek istiyorsanız, belgelenmemiş izleme bayrağı 2398'i kullanabilirsiniz. Örnek bir çıktı:

Akıllı arama maliyeti (7.1) :: 1.34078e + 154, 0.001

Bu örnek, maliyet üst sınırı ve 0.001 faktörü gösteren not grubu 7, alternatif 1 ile ilgilidir. Daha temiz faktörleri görmek için, sayfaların mümkün olduğunca yoğun olması için tabloları paralellik olmadan yeniden yaptığınızdan emin olun. Bunu yapmadan, örnek Hedef Tablonuz için faktör 0.000821 gibidir. Tabii ki orada oldukça açık bazı ilişkiler var.

SSC belgesiz iz bayrağı 2399 ile de devre dışı bırakılabilir. Bu bayrak etkinken, her iki maliyet de daha yüksek değerdedir.


8

Bunun bir cevap olduğundan emin değilim, ancak yorum yapmak için biraz uzun. Farkın nedeni benim tarafımdaki saf spekülasyondur ve belki de başkalarına düşünce için yiyecek olabilir.

Uygulama planları ile basitleştirilmiş sorgular.

SELECT S.KeyCol, 
       S.OtherCol,
       T.*
FROM staging AS S 
  LEFT OUTER JOIN Target AS T 
    ON T.KeyCol = S.KeyCol;

SELECT S.KeyCol, 
       S.OtherCol,
       T.*
FROM staging AS S 
  LEFT OUTER JOIN (
                  SELECT *
                  FROM Target
                  ) AS T 
    ON T.KeyCol = S.KeyCol;

görüntü tanımını buraya girin

Aynı uygulama planları ile sonuçlanabilecek bu eşdeğer sorgular arasındaki temel fark, hesaplama skaler operatörüdür. Neden orada olması gerektiğini bilmiyorum ama, optimize edicinin türetilmiş tabloyu en iyi duruma getirmek için gidebildiği kadarıyla olduğunu tahmin ediyorum.

Tahminime göre, skaler hesaplamanın varlığı, ikinci sorgu için GÇ maliyetini düşüren şeydir.

Gönderen Planı Maliyetleme: İçeriden Doktoru

CPU maliyeti, ilk satır için 0.0001581 ve sonraki satırlar için 0.000011 olarak hesaplanır.
...
0.003125'in G / Ç maliyeti tam olarak 1/320'dir - modelin, disk alt sisteminin saniyede 320 rastgele G / Ç işlemi gerçekleştirebileceği varsayımını yansıtan
...
maliyetlendirme bileşeni, toplam tutarın Diskten getirilmesi gereken sayfalar, tüm tablonun saklanması için gereken sayfa sayısını asla aşamaz.

Benim durumumda tablo 5618 sayfa alıyor ve 1000000 satırdan 1000 satır almak için gereken tahmini sayfa sayısı 5.618, IO Maliyetini 0.015625 olarak veriyor.

Her iki sorgu için CPU Maliyeti aynı olacaktır 0.0001581 * 1000 executions = 0.1581.

Bu nedenle, yukarıda belirtilen makaleye göre, ilk sorgu için maliyeti 0,173725 olarak hesaplayabiliriz.

Hesaplama skalerinin nasıl bir GÇ Maliyetine yol açtığı konusunda haklı olduğumu farz edersek, 3.2831 olarak hesaplanabilir.

Planlarda gösterilen tam olarak ne değil ama mahallede tam da orada.


6

(Bu Paul'ün cevabına bir yorum olarak daha iyi olurdu, ama henüz yeterince bilgim yok.)

DBCCGelecekte de benzer tutarsızlıkları araştırmakta fayda var diye iz bayraklarının (ve birkaç ifadenin) listesini vermek istedim . Bunların hepsi üretimde kullanılmamalıdır .

İlk olarak, hangi fiziksel operatörlerin kullanıldığını görmek için Son Not'a bir göz attım . Grafik uygulama planlarına göre kesinlikle aynı gözüküyorlar. Böylece iz bayraklarını kullandım 3604ve 8615ilk çıktıyı müşteriye yönlendiriyor, ikincisi son notu gösteriyor:

SELECT S.*, T.KeyCol
FROM Staging AS S
      LEFT OUTER JOIN Target AS T
       ON T.KeyCol = S.KeyCol
OPTION(QUERYTRACEON 3604, -- Output client info
       QUERYTRACEON 8615, -- Shows Final Memo structure
       RECOMPILE);

Ondan geriye doğru takip ederek Root Groupneredeyse aynı PhyOp_Rangeoperatörleri buldum :

  1. PhyOp_Range 1 ASC 2.0 Cost(RowGoal 0,ReW 0,ReB 999,Dist 1000,Total 1000)= 0.175559(Distance = 2)
  2. PhyOp_Range 1 ASC 3.0 Cost(RowGoal 0,ReW 0,ReB 999,Dist 1000,Total 1000)= 3.01702(Distance = 2)

Bana sadece belirgin fark olduğunu 2.0ve 3.0kendi "not grubunda 2, orijinal" ve "orijinal not grup 3," bakın, hangi. Notu kontrol ederken, bunlar aynı şeyi ifade eder - bu yüzden henüz bir fark bulunmamıştır.

İkincisi, bana verimsiz gelen, ama ilginç bir içeriğe sahip olan bir sürü iz bayrağı karmaşasına baktım. Ben en kaldırdı Benjamin Nevarez . Bir durumda uygulanan diğerine değil optimizasyon kurallarına dair ipuçları arıyordum.

 SELECT S.*, T.KeyCol
 FROM Staging AS S
      LEFT OUTER JOIN Target AS T
        ON T.KeyCol = S.KeyCol
 OPTION (QUERYTRACEON 3604, -- Output info to client
         QUERYTRACEON 2363, -- Show stats and cardinality info
         QUERYTRACEON 8675, -- Show optimization process info
         QUERYTRACEON 8606, -- Show logical query trees
         QUERYTRACEON 8607, -- Show physical query tree
         QUERYTRACEON 2372, -- Show memory utilization info for optimization stages 
         QUERYTRACEON 2373, -- Show memory utilization info for applying rules
         RECOMPILE );

Üçüncüsü, PhyOp_Rangebenzer kurallar için hangi kuralların uygulandığına baktım . Bir blog yazısında Paul'un bahsettiği birkaç iz bayrağı kullandım .

SELECT S.*, T.KeyCol
FROM Staging AS S
      LEFT OUTER JOIN (SELECT KeyCol
                      FROM Target) AS T
       ON T.KeyCol = S.KeyCol
OPTION (QUERYTRACEON 3604, -- Output info to client
        QUERYTRACEON 8619, -- Show applied optimization rules
        QUERYTRACEON 8620, -- Show rule-to-memo info
        QUERYTRACEON 8621, -- Show resulting tree
        QUERYTRACEON 2398, -- Show "smart seek costing"
        RECOMPILE );

Çıktı, biz direkt-görüyoruz JOINbizim almak için bu kuralı uygulanır PhyOp_Rangeoperatörünü: Rule Result: group=7 2 <SelIdxToRng>PhyOp_Range 1 ASC 2 (Distance = 2). Alt seçim yerine bu kuralı uygulanır: Rule Result: group=9 2 <SelToIdxStrategy>PhyOp_Range 1 ASC 3 (Distance = 2). Burası ayrıca her kuralla ilgili "akıllı arama maliyeti" bilgisini gördüğünüz yerdir. Yönelimlilik için JOINbu (benim için) çıktısı: Smart seek costing (7.2) :: 1.34078e+154 , 0.001. Subselect için bu çıktısı şöyledir: Smart seek costing (9.2) :: 1.34078e+154 , 1.

Sonunda fazla bir şey yapamadım - ama Paul'un cevabı bu boşluğu kapattı. Akıllı arama maliyeti hakkında daha fazla bilgi görmek isterim.


4

Bu da ya bir cevap değil - Mikael'in dediği gibi, yorumlarda bu sorunu tartışmak zor ...

İlginçtir ki, alt sorguyu (select KeyCol FROM Target)satır içi bir TVF'ye dönüştürürseniz, planın ve maliyetlerinin basit orijinal sorgu ile aynı olduğunu görürsünüz:

CREATE FUNCTION dbo.cs_test()
RETURNS TABLE
WITH SCHEMABINDING
AS 
RETURN (
    SELECT KeyCol FROM dbo.Target
    );

/* "normal" variant */
SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN Target AS T ON T.KeyCol = S.KeyCol;

/* "subquery" variant */
SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN (SELECT KeyCol FROM Target) AS T ON T.KeyCol = S.KeyCol;

/* "inline-TVF" variant */
SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN dbo.cs_test() t ON s.KeyCol = t.Keycol

Sorgu planları ( pastetheplan bağlantısı ):

görüntü tanımını buraya girin

Tümdengelim, maliyet motorunun bu tür bir alt sorgunun olası etkisi ile ilgili olarak kafamın karıştığına inanmamı sağlıyor .

Örneğin, aşağıdakileri ele alalım:

SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN (
        SELECT KeyCol = CHECKSUM(NEWID()) 
        FROM Target
        ) AS T ON T.KeyCol = S.KeyCol;

Nasıl olur sen o mal? Sorgu en iyi duruma getiricisi , bir hesaplama skalası içeren yukarıdaki "alt sorgu" varyantına çok benzer bir plan seçti ( pastetheplan.com bağlantısı ):

görüntü tanımını buraya girin

Hesaplama skalerinin yukarıda gösterilen "alt sorgu" varyantından oldukça farklı bir maliyeti vardır, ancak sorgu optimizerinin bildiği hiçbir yolu olmadığı için bir tahmin, bir priori, döndürülen satır sayısının ne olabileceğine dair bir tahmin. Plan, sol tahminler için karma eşleşmeyi kullanır, çünkü satır tahminleri bilinmezdir ve bu nedenle Hedef tablosundaki satır sayısına ayarlanmıştır.

görüntü tanımını buraya girin

Mikael'in cevabında yaptığı işe katılıyorum dışında başka birisinin daha iyi bir sonucuna sahip değilim ve başka birinin daha iyi bir cevap bulabilmesi umuduyla.

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.