Faktor-faktor apa yang masuk ke Indeks Clustered View yang diindeks yang dipilih?

19

Secara singkat
Faktor-faktor apa yang masuk ke dalam mereka kueri pemilihan pengoptimal dari indeks tampilan diindeks?

Bagi saya, tampilan yang diindeks tampaknya menentang apa yang saya pahami tentang bagaimana Pengoptimal mengambil indeks. Saya pernah melihat ini bertanya sebelumnya , tetapi OP tidak diterima dengan baik. Saya benar-benar mencari guidepost , tapi saya akan membuat contoh pseudo, lalu memposting contoh nyata dengan banyak DDL, output, contoh.

Asumsikan saya menggunakan Enterprise 2008+, mengerti with(noexpand)

Contoh semu

Ambil contoh semu ini: Saya membuat tampilan dengan 22 gabungan, 17 filter, dan poni sirkus yang melintasi sekelompok 10 juta tabel baris. Pandangan ini mahal (ya, dengan huruf besar E) untuk terwujud. Saya akan SCHEMABIND dan Indeks tampilan. Lalu a SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84. Dalam logika Pengoptimal yang menghindari saya, gabungan yang mendasarinya dilakukan.

Hasil:

  • Tidak Petunjuk: 4825 dibaca untuk 720 baris, 47 cpu lebih dari 76ms, dan perkiraan biaya sub pohon 0,30523.
  • Dengan Petunjuk: 17 kali dibaca, 720 baris, 15 cpu lebih dari 4ms, dan perkiraan biaya subtree sebesar 0,007253

Jadi apa yang terjadi di sini? Saya sudah mencobanya di Enterprise 2008, 2008-R2 dan 2012. Dengan setiap metrik yang saya pikirkan menggunakan indeks tampilan jauh lebih efisien. Saya tidak memiliki masalah parameter sniffing atau data miring, karena ini ad hock.

Contoh Nyata (Panjang)

Kecuali Anda seorang masokis sentuhan, Anda mungkin tidak perlu atau ingin membaca bagian ini.

Versi
Yap, perusahaan.

Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 10 Februari 2012 19:39:15 Hak cipta (c) Microsoft Corporation Enterprise Edition (64-bit) pada Windows NT 6.2 (Build 9200:) (Hypervisor)

Pandangan

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

Indeks Berkelompok

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

Uji SQL

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

Hasil = 11 Baris Output

11 baris output - sama untuk kedua query

Output Profiler
4 baris teratas tanpa petunjuk. 4 baris terbawah menggunakan petunjuk.

Profiler

Eksekusi Rencana
GitHub Intis untuk kedua Rencana Eksekusi dalam format SQLPlan

Tidak ada rencana Eksekusi Petunjuk - mengapa tidak menggunakan indeks berkerumun yang saya berikan kepada Anda Mr. SQL? Itu clusterd pada bidang filter 3. Cobalah, Anda mungkin menyukainya.
No Hint - rencana eksekusi besar

Paket sederhana saat menggunakan petunjuk.

Menggunakan Petunjuk - Rencana Eksekusi Sederhana

EBarr
sumber
Diskusi pindah ke obrolan
Paul White mengatakan GoFundMonica

Jawaban:

26

Mencocokkan tampilan yang diindeks adalah operasi yang relatif mahal *, jadi pengoptimal terlebih dahulu mencoba transformasi cepat dan mudah lainnya. Jika itu terjadi untuk menghasilkan rencana murah (0,05 unit dalam kasus Anda) optimasi berakhir lebih awal. Taruhannya adalah bahwa pengoptimalan yang berkelanjutan akan menghabiskan lebih banyak waktu daripada yang dihemat. Ingat tujuan utama pengoptimal adalah rencana 'cukup baik' dengan cepat.

Menggunakan indeks berkerumun pada tampilan tidak dengan sendirinya mahal, tetapi proses pencocokan pohon kueri logis untuk tampilan yang diindeks potensial bisa. Seperti yang saya sebutkan di komentar pada pertanyaan lain, referensi tampilan dalam kueri diperluas sebelum pengoptimalan, jadi pengoptimal tidak tahu Anda yang menulis kueri terhadap tampilan di tempat pertama - hanya melihat struktur yang diperluas (seolah-olah pandangan telah in-line).

"Rencana Cukup Baik" berarti pengoptimal menemukan rencana yang layak dan berhenti lebih awal dalam fase eksplorasi. "TimeOut" berarti melebihi jumlah langkah optimasi yang ditetapkannya sebagai 'anggaran' pada awal fase saat ini.

Anggaran ditetapkan berdasarkan biaya rencana terbaik yang ditemukan pada fase sebelumnya. Dengan kueri berbiaya rendah (0,05), jumlah gerakan yang dianggarkan akan cukup kecil, dan cepat habis oleh transformasi reguler mengingat jumlah gabungan yang terlibat dalam kueri sampel Anda (misalnya, ada banyak cara untuk mengatur ulang gabungan dalam, misalnya) .

Jika Anda tertarik untuk mengetahui lebih lanjut tentang mengapa pencocokan tampilan indeks mahal, dan oleh karena itu pergi ke tahap selanjutnya dari optimasi dan / atau hanya dipertimbangkan untuk pertanyaan yang lebih mahal, ada dua Microsoft Research Papers pada topik di sini (pdf) dan di sini (citeseer ).

Faktor lain yang relevan adalah pencocokan tampilan yang diindeks tidak tersedia dalam fase optimisasi 0 (pemrosesan transaksi).

Bacaan lebih lanjut:

Tampilan dan Statistik Terindeks

* dan hanya tersedia dalam Edisi Perusahaan (atau yang setara)

Paul White mengatakan GoFundMonica
sumber