Bir Dizinlenmiş Görünümün Kümelenmiş Dizini'nin seçilmesinde hangi faktörler etkiliyor?


19

Kısaca
Optimize edicinin dizine eklenen bir görünümün dizinini seçmesini sorgulayan faktörler nelerdir?

Benim için dizinlenmiş görünümler, Doktor'un dizinleri nasıl seçtiğiyle ilgili anladığım şeylere meydan okuyor gibi görünüyor. Bunu daha önce sordum gördüm , ama OP çok iyi karşılanmadı. Gerçekten direkleri arıyorum , ama sahte bir örnek uydurmak, sonra DDL, çıktı, örnekler bir sürü ile gerçek örnek sonrası.

Enterprise 2008+ kullandığımı varsayalım, anlayın with(noexpand)

Sözde Örnek

Bu sözde örneği alın: 22 birleşim, 17 filtre ve 10 milyon satırlık bir tabloyu geçen bir sirk midilli ile bir görünüm oluşturuyorum. Bu görüş gerçekleşmek için Pahalıdır (evet, bir başkent E ile). Ben SCHEMABIND ve görünümü endeksleyeceğim. Sonra a SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84. Beni kaçıran Optimizer mantığında, temeldeki birleşimler gerçekleştirilir.

Sonuç:

  • Hayır İpucu: 4825, 720 satır, 76 ms üzerinde 47 cpu ve tahmini alt ağaç maliyeti 0.30523'ü okur.
  • İpucu: 17 okuma, 720 satır, 4 ms üzerinde 15 işlemci ve tahmini alt ağaç maliyeti 0.007253

Peki burada neler oluyor? Enterprise 2008, 2008-R2 ve 2012'de denedim . Görünümün dizinini kullanmayı düşünebildiğim her metrikte çok daha verimli. Bu reklam hock olduğundan parametre koklama sorunu veya eğri verilerim yok.

Gerçek (Uzun) Bir Örnek

Eğer dokunma mazoşist değilseniz, muhtemelen bu bölümü okumak veya okumak istemezsiniz.

Sürüm
Yep, kurumsal.

Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 10 Şubat 2012 19:39:15 Telif Hakkı (c) Windows NT 6.2 üzerinde Microsoft Corporation Enterprise Edition (64 bit) (Derleme 9200:) (Hipervizör)

Görünüm

CREATE VIEW dbo.TimelineMaterialized    WITH SCHEMABINDING
AS
SELECT  TM.TimelineID,
        TM.TimelineTypeID,
        TM.EmployeeID,
        TM.CreateUTC,
        CUL.CultureCode,
        CASE 
           WHEN TM.CustomerMessageID    > 0 THEN TM.CustomerMessageID
           WHEN TM.CustomerSessionID    > 0 THEN TM.CustomerSessionID
           WHEN TM.NewItemTagID         > 0 THEN TM.NewItemTagID
           WHEN TM.OutfitID             > 0 THEN TM.OutfitID
           WHEN TM.ProductTransactionID > 0 THEN TM.ProductTransactionID
           ELSE 0 END  As HrefId,
        CASE 
          WHEN TM.CustomerMessageID    > 0 THEN IsNull(C.Name, 'N/A')   
          WHEN TM.CustomerSessionID    > 0 THEN IsNull(C.Name, 'N/A')
          WHEN TM.NewItemTagID         > 0 THEN IsNull(NI.Title, 'N/A')
          WHEN TM.OutfitID             > 0 THEN IsNull(O.Name, 'N/A')
          WHEN TM.ProductTransactionID > 0 THEN IsNull(PT_PL.NameLocalized, 'N/A')
                 END as HrefText

FROM       dbo.Timeline TM
INNER JOIN dbo.CustomerSession    CS    ON TM.CustomerSessionID    = CS.CustomerSessionID
INNER JOIN dbo.CustomerMessage    CM    ON TM.CustomerMessageID    = CM.CustomerMessageID
INNER JOIN dbo.Outfit             O     ON PO.OutfitID             = O.OutfitID
INNER JOIN dbo.ProductTransaction PT    ON TM.ProductTransactionID = PT.ProductTransactionID
INNER JOIN dbo.Product            PT_P  ON PT.ProductID            = PT_P.ProductID
INNER JOIN dbo.ProductLang        PT_PL ON PT_P.ProductID          = PT_PL.ProductID
INNER JOIN dbo.Culture            CUL   ON PT_PL.CultureID         = CUL.CultureID
INNER JOIN dbo.NewsItemTag        NIT   ON TM.NewsItemTagID        = NIT.NewsItemTagID
INNER JOIN dbo.NewsItem           NI    ON NIT.NewsItemID          = NI.NewsItemID
INNER JOIN dbo.Customer           C     ON  C.CustomerID = CASE 
                                             WHEN TM.TimelineTypeID = 1 THEN CM.CustomerID 
                                             WHEN TM.TimelineTypeID = 5 THEN CS.CustomerID
                                             ELSE 0 END

WHERE        CUL.IsActive = 1

Kümelenmiş Dizin

CREATE UNIQUE CLUSTERED INDEX PK_TimelineMaterialized  ON 
                   TimelineMaterialized (EmployeeID, CreateUTC, CultureCode, TimelineID)

SQL'i test et

-- NO HINT - - -  - - -  - - -  - - -  - - - 
SELECT  *                 --yes yes, star is bad ...just a test example
FROM    TimelineMaterialized TM 
WHERE 
            TM.EmployeeID   = 2
        AND TM.CultureCode  = 'en-US'
        AND TM.CreateUTC    > '9/10/2012'
        AND TM.CreateUTC    < '9/11/2012'

-- WITH HINT - - -  - - -  - - -  - - -  - - - 
SELECT  *               
FROM    TimelineMaterialized TM with(noexpand)
WHERE 
            TM.EmployeeID   = 2
        AND TM.CultureCode  = 'en-US'
        AND TM.CreateUTC    > '9/10/2012'
        AND TM.CreateUTC    < '9/11/2012'

Sonuç = 11 Satır Çıktı

11 satır çıktı - her iki sorgu için aynı

Profiler Çıkışı
En üstteki 4 satır ipucu içermez. En alttaki 4 satır ipucunu kullanıyor.

Profiler

Yürütme Planları
GitHub Gist, SQLPlan biçimindeki her iki Yürütme Planı için

Hayır İpucu Yürütme planı - neden size SQL verdi kümelenmiş dizin kullanmıyorsunuz? 3 filtre alanında kümelenmiştir. Bir dene, belki hoşuna gider.
İpucu yok - büyük yürütme planı

Bir ipucu kullanırken basit bir plan.

İpucu Kullanma - Basit Yürütme Planı


Yanıtlar:


26

Dizine alınmış görünümleri eşleştirmek nispeten pahalı bir işlemdir *, bu nedenle optimize edici önce diğer hızlı ve kolay dönüşümleri dener. Eğer bunlar ucuz bir plan (durumunuzda 0,05 birim) üretirse optimizasyon erken sona erer. Bahis, sürekli optimizasyonun kaydettiğinden daha fazla zaman harcayacağıdır. Optimize edicinin birincil hedefinin hızlı bir şekilde 'yeterince iyi' bir plan olduğunu unutmayın.

Kümelenmiş dizini görünümde kullanmak kendi başına pahalı değildir, ancak mantıksal bir sorgu ağacını olası dizine eklenmiş görünümlerle eşleştirme işlemi olabilir. Diğer soruya yapılan bir yorumda belirttiğim gibi, sorgudaki görünüm referansı optimizasyondan önce genişletildi, bu nedenle optimize edici sorguyu görünüme karşı ilk başta yazdığınızı bilmiyor - yalnızca genişletilmiş ağacı görüyor ( görünüm sıraya dizilmişti).

"Yeterli Yeterli Plan", optimize edicinin iyi bir plan bulduğu ve arama aşamasında erken durdurulduğu anlamına gelir. "TimeOut", mevcut aşamanın başlangıcında kendisini 'bütçe' olarak ayarladığı optimizasyon adımlarının sayısını aştığı anlamına gelir.

Bütçe, önceki bir aşamada bulunan en iyi planın maliyetine göre belirlenir. Böyle düşük maliyetli bir sorgu ile (0,05), bütçelenmiş hareketlerin sayısı oldukça az olacaktır ve örnek sorgunuza dahil olan birleşimlerin sayısı göz önüne alındığında düzenli dönüşümle hızlı bir şekilde tükenecektir (örneğin, iç birleşimleri yeniden düzenlemenin birçok yolu vardır) .

Eğer endeksli görünüm eşleştirme pahalı olmasının nedeni hakkında daha fazla bilgi edinmek isteyen ve bu nedenle daha sonraki optimizasyon aşamalarında ve / veya sadece daha pahalı sorguları için düşünülen, konuyla ilgili iki Microsoft Research Papers vardır için sol ise burada (pdf) ve burada (citeseer ).

İlgili diğer bir faktör de, dizinlenmiş görünüm eşleştirmenin optimizasyon aşaması 0'da (işlem işleme) bulunmamasıdır.

Daha fazla okuma:

Dizine Eklenmiş Görünümler ve İstatistikler

* ve yalnızca Enterprise Edition'da (veya eşdeğeri) kullanılabilir

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.