Yürütme planı pahalı CONVERT_IMPLICIT işlemi gösterir. Bunu indekslemeyle düzeltebilir miyim, yoksa tabloyu değiştirmem gerekir mi?


24

Nerede olduğu koşulunda bunun gibi gerçekten çirkin koşulları içeren çok önemli ve çok yavaş bir görüşüm var. Ayrıca, birleştirme işlemlerinin varchar(13)tam sayı kimlik alanları yerine brüt ve yavaş katılımlar olduğunu , ancak bu görünümü kullanan aşağıdaki basit sorguyu geliştirmek istediğimi biliyorum:

CREATE VIEW [dbo].[vwReallySlowView]  AS  
AS  
SELECT     
  I.booking_no_v32 AS bkno, 
  I.trans_type_v41 AS trantype, 
  B.Assigned_to_v61 AS Assignbk, 
  B.order_date AS dateo, B.HourBooked AS HBooked,   
  B.MinBooked AS MBooked, B.SecBooked AS SBooked, 
  I.prep_on AS Pon, I.From_locn AS Flocn, 
  I.Trans_to_locn AS TTlocn,   
                      (CASE I.prep_on WHEN 'Y' THEN I.PDate ELSE I.FirstDate END) AS PrDate, I.PTimeH AS PrTimeH, I.PTimeM AS PrTimeM,   
                      (CASE WHEN I.RetnDate < I.FirstDate THEN I.FirstDate ELSE I.RetnDate END) AS RDatev, I.bit_field_v41 AS bitField, I.FirstDate AS FDatev, I.BookDate AS DBooked,   
                      I.TimeBookedH AS TBookH, I.TimeBookedM AS TBookM, I.TimeBookedS AS TBookS, I.del_time_hour AS dth, I.del_time_min AS dtm, I.return_to_locn AS rtlocn,   
                      I.return_time_hour AS rth, I.return_time_min AS rtm, (CASE WHEN I.Trans_type_v41 IN (6, 7) AND (I.Trans_qty < I.QtyCheckedOut)   
                      THEN 0 WHEN I.Trans_type_v41 IN (6, 7) AND (I.Trans_qty >= I.QtyCheckedOut) THEN I.Trans_Qty - I.QtyCheckedOut ELSE I.trans_qty END) AS trqty,   
                      (CASE WHEN I.Trans_type_v41 IN (6, 7) THEN 0 ELSE I.QtyCheckedOut END) AS MyQtycheckedout, (CASE WHEN I.Trans_type_v41 IN (6, 7)   
                      THEN 0 ELSE I.QtyReturned END) AS retqty, I.ID, B.BookingProgressStatus AS bkProg, I.product_code_v42, I.return_to_locn, I.AssignTo, I.AssignType,   
                      I.QtyReserved, B.DeprepOn,  
        (CASE  B.DeprepOn       
        WHEN 1 THEN  B.DeprepDateTime     
        ELSE   I.RetnDate  
           END)  AS DeprepDateTime, I.InRack 
FROM         dbo.tblItemtran AS I 

INNER JOIN  -- booking_no = varchar(13)
         dbo.tblbookings AS B ON B.booking_no = I.booking_no_v32  --  string inner-join

INNER JOIN  -- product_code = varchar(13) 
        dbo.tblInvmas AS M ON I.product_code_v42 = M.product_code  --  string inner-join

WHERE     (I.trans_type_v41 NOT IN (2, 3, 7, 18, 19, 20, 21, 12, 13, 22)) AND (I.trans_type_v41 NOT IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) OR  
                      (I.trans_type_v41 NOT IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) AND (B.BookingProgressStatus = 1) OR  
                      (I.trans_type_v41 IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) AND (I.QtyCheckedOut = 0) OR  
                      (I.trans_type_v41 IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) AND (I.QtyCheckedOut > 0) AND (I.trans_qty - (I.QtyCheckedOut - I.QtyReturned) > 0)  

Bu görünüm genellikle şöyle kullanılır:

select * from vwReallySlowView
where product_code_v42  = 'LIGHTBULB100W'  -- find "100 watt lightbulb" rows

Onu çalıştırdığınızda ben yüklem ile, toplu toplam maliyetinin 20 ila 80% maliyet Bu yürütme planı öğeyi almak CONVERT_IMPLICIT( .... &(4))yaptığını çok yavaş gibi görünüyor gösteren bitwise boolean testsgibi (I.ibitfield & 4 = 0).

Ben çoğu zaman SQL olmayan bir yazılım geliştiricisi olduğum için genel olarak MS SQL veya DBA tipi işlerde uzman değilim. Ancak, bu tür bitsel kombinasyonların kötü bir fikir olduğundan ve ayrık boolean alanlara sahip olmanın daha iyi olacağından şüpheleniyorum.

Bir şekilde ben bu endeksini yükseltmek Could, daha iyi (binlerce şubesi üretimin zaten var) şemayı değiştirmeden bu görüşü ele almak ya da ben bir tamsayı içine paketlenmiş çeşitli boolean değerlere sahip altta yatan tabloyu değiştirmek gerekir bit_field_v41bu sorunu çözmeye yönelik, ?

İşte tblItemtranbu yürütme planında taranmakta olan Kümelenmiş Dizin :

-- goal:  speed up  select * from vwReallySlowView where productcode  = 'X'
CREATE CLUSTERED INDEX [idxtblItemTranProductCodeAndTransType] ON [dbo].[tblItemtran] 
(
    [product_code_v42] ASC,  -- varchar(13)
    [trans_type_v41] ASC     -- int
)WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, 
        IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, 
        ALLOW_PAGE_LOCKS  = ON) 
ON [PRIMARY]

İşte bu CONVERT_IMPLICITöngörüde % 27 maliyete neden olan diğer ürünlerden biri için uygulama planı . update Bu durumda, en kötü düğümümün şu anda " inner join% eşleşmesi" olduğunu ve % 34'e mal olduğunu unutmayın. Şu anda yapamadığım dizgelere katılmaktan kaçınamadığım sürece, bunun kaçınamayacağım bir maliyet olduğuna inanıyorum. kurtulmak. INNER JOINYukarıdaki görünümdeki her iki işlem de alan üzerindedir varchar(13).

Sağ alt köşeye yakınlaştırılmış:

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

.Sqlplan olarak bütün uygulama planlarını skydrive'da bulabilirsiniz. Bu görüntü sadece görsel bir genel bakış. Resmi kendi başına görmek için buraya tıklayın .

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

Güncelleme, yürütme planının tamamını yayınladı. product_codePatolojik olarak hangi değerin kötü olduğunu bulamıyorum , ancak select count(*) from viewbunu yapmanın bir yolu tek bir ürün yapmak yerine. Ancak, alttaki tablodaki kayıtların yalnızca% 5'inde kullanılan ürünler CONVERT_IMPLICIT operasyonda çok daha düşük maliyetler gösteriyor gibi görünüyor . Eğer burada SQL'i düzeltecek olsaydım WHERE, görünümdeki genel maddeyi alırdım ve bu dev where-yan tümcesinin sonucunu, aşağıdaki tabloda "IncludeMeInTheView" bit-alanı olarak hesaplar ve saklardım. . Presto, problem çözüldü değil mi?



Ben yayınlanan .SQLPLAN orijinal görüntüdeki 432k / 17k durumundan daha az patolojiktir. Verilerimle product_codebu patolojik 87%durumu oluşturmak için kullandığım değeri artık bulamadığım için özür dilerim . Görüntüler şimdi gösteriliyor 27%. Yine, düzenlemelerimden dolayı oluşan karışıklık için özür dilerim.
Warren P,

Yanıtlar:


49

İcra planlarında maliyet yüzdelerine çok fazla güvenmemelisiniz. Bunlar, her zaman tahmini sayılar gibi şeyler için 'gerçek' sayıları olan icra sonrası planlarda bile hesaplanır . Tahmini maliyetler, amaçlandığı amaç için oldukça iyi çalışan bir modele dayanmaktadır: optimize edicinin aynı sorgu için farklı aday yürütme planları arasında seçim yapmasını sağlamak. Maliyet bilgisi ilginç ve dikkate alınması gereken bir faktördür, ancak nadiren sorgu ayarlama için birincil bir ölçüm olmalıdır. Yürütme planı bilgisini yorumlamak, sunulan verilere daha geniş bir bakış açısı gerektirir.

ItemTran Kümelenmiş Endeks Ara Operatör

ItemTran Kümelenmiş Dizin Ara

Bu operatör bir arada gerçekten iki işlem. İlk önce bir dizin arama işlemi, yüklem ile eşleşen tüm satırları bulur product_code_v42 = 'M10BOLT', ardından her satırda kalan artık yüklemeyi bit_field_v41 & 4 = 0uygular. bit_field_v41Temel türünden ( tinyintveya smallint) diline kadar örtük bir dönüşüm var integer.

Dönüşüm, bitwise-AND işleci (&) her iki işlecin de aynı türde olmasını gerektirdiğinden gerçekleşir. '4' sabit değerinin örtülü türü tamsayıdır ve veri türü öncelik kuralları , düşük öncelikli bit_field_v41alan değerinin dönüştürüldüğü anlamına gelir .

Sorun (olduğu gibi), yüklemin yazılmasıyla kolayca giderilir bit_field_v41 & CONVERT(tinyint, 4) = 0- yani sabit değer düşük önceliğe sahiptir ve sütun değeri yerine (sabit katlama sırasında) dönüştürülür. Değilse bit_field_v41, tinyinthiç dönüşüm gerçekleşmez. Aynı şekilde CONVERT(smallint, 4)eğer öyleyse bit_field_v41kullanılabilir smallint. Bununla birlikte , dönüşüm bu durumda bir performans sorunu değildir , ancak türleri eşleştirmek ve mümkünse örtük dönüşümlerden kaçınmak hala iyi bir uygulamadır.

Bu arayışın tahmini maliyetinin büyük kısmı temel tablonun boyutuna düşmektedir. Kümelenmiş indeks tuşunun kendisi oldukça dar olsa da, her satırın boyutu büyüktür. Tablo için bir tanım verilmez, ancak yalnızca görünümde kullanılan sütunlar önemli bir satır genişliğine eklenir. Kümelenmiş dizin tüm sütunları içerdiğinden, kümelenmiş dizin şifreler arasındaki mesafe genişliği satır değil, genişliği göstergesi şifreler . Bazı sütunlarda sürüm soneklerinin kullanılması, gerçek tablonun önceki sürümler için daha da fazla sütuna sahip olduğunu gösterir.

Arama, artık kestirim ve çıktı sütunlarına bakıldığında, bu operatörün performansı eşdeğer sorgu oluşturularak izole edilebilir ( 1 <> 2oto-parametrelemeyi engellemek için bir püf noktasıdır, çelişki optimizer tarafından kaldırılır ve görünmüyor sorgu planı):

SELECT
    it.booking_no_v32,
    it.QtyCheckedOut,
    it.QtyReturned,
    it.Trans_qty,
    it.trans_type_v41
FROM dbo.tblItemTran AS it
WHERE
    1 <> 2
    AND it.product_code_v42 = 'M10BOLT'
    AND it.bit_field_v41 & CONVERT(tinyint, 4) = 0;

Bu sorgunun soğuk bir veri önbelleğiyle gösterilmesi ilgi çekicidir, çünkü okumaya devam etme tablo (kümelenmiş dizin) parçalanmasından etkilenir. Bu tablonun kümelenme anahtarı parçalanmaya davet eder, bu nedenle bu dizini düzenli olarak muhafaza etmek (yeniden düzenlemek veya yeniden oluşturmak) ve FILLFACTORdizin bakım pencereleri arasında yeni satırlar için boşluk bırakmak için uygun bir yöntem kullanmak önemli olabilir .

SQL Data Generator kullanılarak oluşturulan örnek verileri kullanarak parçalanmanın okumaya devam etme üzerindeki etkisini test ettim . Aynı tablo satırını kullanarak, sorunun sorgu planında gösterildiği gibi sayıları yüksek oranda bölünmüş kümelenmiş bir indeks SELECT * FROM view15 saniye sonra almaya başladı DBCC DROPCLEANBUFFERS. Aynı test, ItemTrans tablosundaki yeni bir şekilde yeniden oluşturulmuş kümelenmiş indeks ile aynı koşullarda 3 saniyede tamamlandı.

Tablo verileri genellikle tamamen önbellekte ise, parçalanma sorunu çok daha az önemlidir. Ancak, düşük parçalanmada bile, geniş tablo satırları mantıksal ve fiziksel okumaların sayısının beklenenden çok daha yüksek olduğu anlamına gelebilir. Ayrıca CONVERT, en iyi uygulama ihlali dışında, örtük dönüşüm konusunun burada önemli olmadığı yönündeki beklentimi doğrulamak için açık bir şekilde ekleme ve kaldırma denemesi yapabilirsiniz .

Daha önemlisi, arama operatöründen ayrılan tahmini satır sayısıdır. Optimizasyon süresi tahmini 165 satırdır, ancak 4.226 yürütme zamanında üretildi. Daha sonra bu noktaya döneceğim, ancak tutarsızlığın ana nedeni, artık yüklemin seçiciliğinin (bit yönünde-VE içeren) seçiciliğin tahmin etmesi için çok zor olmasıdır - aslında tahmin etmeye başvurur.

Filtre Operatörü

Filtre Operatörü

Burada, iki NOT INlistenin nasıl birleştirildiğini, basitleştirildiğini ve genişletildiğini ve ayrıca aşağıdaki karma eşleşmesi tartışması için bir referans sağladığını gösteren filtre göstergesini burada gösteriyorum . Aramadan gelen test sorgusu, etkilerini içerecek ve Filter operatörünün performans üzerindeki etkisini belirleyecek şekilde genişletilebilir:

SELECT
    it.booking_no_v32,
    it.trans_type_v41,
    it.Trans_qty,
    it.QtyReturned,
    it.QtyCheckedOut
FROM dbo.tblItemTran AS it
WHERE
    it.product_code_v42 = 'M10BOLT'
    AND it.bit_field_v41 & CONVERT(tinyint, 4) = 0
    AND
    (
        (
            it.trans_type_v41 NOT IN (2, 3, 6, 7, 18, 19, 20, 21, 12, 13, 22)
            AND it.trans_type_v41 NOT IN (6, 7)
        )
        OR
        (
            it.trans_type_v41 NOT IN (6, 7)
        )
        OR 
        (
            it.trans_type_v41 IN (6, 7)
            AND it.QtyCheckedOut = 0
        )
        OR 
        (
            it.trans_type_v41 IN (6, 7)
            AND it.QtyCheckedOut > 0
            AND it.trans_qty - (it.QtyCheckedOut - it.QtyReturned) > 0
        )
    );

Plandaki Scalar Hesaplama işleci aşağıdaki ifadeyi tanımlar (sonuç daha sonraki bir işleç tarafından istenene kadar hesaplamanın kendisi ertelenir):

[Expr1016] = (trans_qty - (QtyCheckedOut - QtyReturned))

Karma Eşleşme Operatörü

Karakter veri türlerinde bir birleştirme gerçekleştirmek, bu operatörün tahmini yüksek maliyetinin nedeni değildir. SSMS araç ipucu sadece bir Hash Keys Probe girişi gösterir, ancak önemli detaylar SSMS Özellikleri penceresindedir.

Karma Eşleme işleci booking_no_v32, ItemTran tablosundaki sütunun (Hash Keys Build) değerlerini kullanarak bir karma tablosu oluşturur ve ardından booking_noBookings tablosundaki sütunu (Hash Keys Probe) kullanarak eşleşmeler için sondalar . SSMS araç ipucu da normalde bir Probu Kalıntısı gösterir, ancak metin bir araç ipucu için çok uzundur ve atlanmıştır.

Prob Kalıntısı, endeksin daha önce aranmasından sonra görülen Kalıntıya benzer; Artık tahmin, sıranın ana operatöre geçirilip geçirilmeyeceğini belirlemek için eşleşen tüm satırlarda değerlendirilir. İyi dengelenmiş bir karışma tablosunda karma eşleşmeleri bulmak son derece hızlıdır, ancak eşleşen her satıra karmaşık bir kalıntı yüklemi uygulamak karşılaştırmaya göre oldukça yavaştır. Plan Gezgini'ndeki Karma Eşleşmesi araç ipucu, Probu Artık ifadesi dahil ayrıntıları gösterir:

Karma Eşleşme Operatörü

Artık tahmin karmaşık bir işlemdir ve şimdi rezervasyon tablosunda bu sütunun mevcut olduğunu gösteren rezervasyon durumu durum kontrolünü içerir. Araç ipucu ayrıca, dizin aramada daha önce görülen tahmini ve gerçek satır sayısı arasındaki aynı farkı gösterir. Filtrelemenin çoğunun iki kez gerçekleştirilmesi garip görünebilir, ancak bu sadece optimizer olanı iyimser. Herhangi bir sırayı ortadan kaldırmak için planın sondadan planı aşağı itilebilecek filtre parçalarının beklemesini beklemiyor (sıra sayısı tahminleri filtre öncesi ve sonrasında aynıdır) ancak en iyisi bu konuda yanlış olabileceğini biliyor. Satırları erken filtreleme şansı (karma birleşimin maliyetini düşürme), ekstra filtrenin küçük maliyetine değer. Tüm filtre aşağı itilemez çünkü rezervasyon tablosundaki bir sütunda bir test içerir, ancak çoğu olabilir.

Satır sayısı hafife alması, Karma Eşleme işleci için bir sorundur, çünkü karma tablo için ayrılan bellek miktarı, tahmini satır sayısını temel alır. Bellek (nedeniyle satır daha fazla sayıda) çalıştırma sırasında gerekli olan karma tablosu boyutu için çok küçük olması halinde karma tablo yinelemeli sızıntılarına fiziksel Tempdb çok zayıf bir performans ile sonuçlanır, depolama. En kötü durumda, yürütme motoru yinelemeli olarak karma kovaları dökerek durur ve çok yavaş yavaş hareket ederkurtarma algoritması. Karma dökülme (özyinelemeli veya kurtarma), soruda belirtilen performans sorunlarının en muhtemel nedenidir (karakter tipi birleştirme sütunları veya örtük dönüşümler değil). Kök neden, sunucunun yanlış satır sayısı (kardinalite) tahminine dayanan sorgu için çok az bellek ayırmasıdır.

Ne yazık ki, SQL Server 2012'den önce, yürütme planında bir karma işleminin bellek tahsisini aştığına dair herhangi bir belirti yoktur (yürütme başlamadan önce, sunucuda boş bellek yığınları olsa bile, ayrılmadan sonra dinamik olarak büyüyemez) ve tempdb. Profiler kullanarak Hash Warning Olay Sınıfını izlemek mümkündür , ancak uyarıları belirli bir sorgu ile ilişkilendirmek zor olabilir.

Sorunları düzeltmek

Üç konu parçalanma, karma prob operatöründe kalan karmaşık prob ve endeks arayışındaki tahminlerden kaynaklanan yanlış kardinalite tahminidir.

Önerilen çözüm

Parçalanmayı kontrol edin ve gerekirse düzeltin, endeksin kabul edilebilir şekilde organize kalmasını sağlamak için bakım planlayın. Kardinalite tahminini düzeltmenin olağan yolu, istatistik sağlamaktır. Bu durumda, optimize edicinin kombinasyon ( product_code_v42, bitfield_v41 & 4 = 0) için istatistiklere ihtiyacı vardır . Doğrudan bir ifadeyle ilgili istatistikler oluşturamıyoruz, bu nedenle önce bit alanı ifadesi için hesaplanmış bir sütun oluşturmalı ve sonra el ile çok sütunlu istatistikleri oluşturmalıyız:

ALTER TABLE dbo.tblItemTran
ADD Bit3 AS bit_field_v41 & CONVERT(tinyint, 4);

CREATE STATISTICS [stats dbo.ItemTran (product_code_v42, Bit3)]
ON dbo.tblItemTran (product_code_v42, Bit3);

Hesaplanan sütun metni tanımı, görünüm tanımındaki metinle tam olarak kullanılacak istatistikler için eşleşmelidir, bu nedenle örtük dönüştürmeyi ortadan kaldırmak için görünümün düzeltilmesi aynı anda yapılmalı ve metin eşleşmesinin sağlanmasına özen gösterilmelidir.

Çok sütunlu istatistikler çok daha iyi tahminlere yol açmalı, karma eşleme operatörünün özyinelemeli dökülme veya kurtarma algoritması kullanması olasılığını büyük ölçüde azaltmalı. Hesaplanan sütunun eklenmesi (yalnızca meta veri olan bir işlemdir ve tabloda işaretli olmadığı için yer yoktur PERSISTED) ve çok sütunlu istatistikler ilk çözümüm için en iyi tahminimdir.

Sorgu performansı sorunlarını çözerken, geçen zaman, CPU kullanımı, mantıksal okumalar, fiziksel okumalar, bekleme türleri ve süreleri gibi şeyleri ölçmek önemlidir. Yukarıda gösterildiği gibi şüpheli nedenleri doğrulamak için sorgunun bölümlerini ayrı ayrı çalıştırmak da faydalı olabilir.

Verilerin ikinci görünümünün önemli olmadığı bazı ortamlarda, tüm görünümü sık sık anlık görüntü tablosuna dönüştüren bir arka plan işlemi çalıştırmak yararlı olabilir. Bu tablo sadece normal bir temel tablodur ve güncelleme performansını etkilemekten endişe etmeden okuma sorguları için endekslenebilir.

Endekslemeyi görüntüle

Orijinal görünümü doğrudan endekslemeye özendirmeyin. Okuma performansı inanılmaz derecede hızlı olacak (görünüm dizininde tek bir arama) ancak (bu durumda) mevcut sorgu planlarındaki tüm performans sorunları, görünümde referans verilen tablo sütunlarından herhangi birini değiştiren sorgulara aktarılacaktır. Temel tablo satırlarını değiştiren sorgular gerçekten de çok etkilenecektir.

Kısmi indeksli görünüme sahip gelişmiş çözüm

Kardinalite tahminlerini düzelten ve filtreyi ve prob kalıntısını gideren ve kaldıran bu özel sorgu için kısmi bir indekslenmiş-görüntüleme çözümü vardır, ancak verilerle ilgili bazı varsayımlara dayanır (çoğunlukla şemadaki benim tahminim) ve özellikle uygun olanlarla ilgili uzman uygulaması gerektirir Dizin oluşturulmuş görünüm bakım planlarını desteklemek için dizinler. Aşağıdaki kodu ilgi için paylaşıyorum, çok dikkatli bir analiz ve test yapmadan uygulamanızı önermiyorum .

-- Indexed view to optimize the main view
CREATE VIEW dbo.V1
WITH SCHEMABINDING
AS
SELECT
    it.ID,
    it.product_code_v42,
    it.trans_type_v41,
    it.booking_no_v32,
    it.Trans_qty,
    it.QtyReturned,
    it.QtyCheckedOut,
    it.QtyReserved,
    it.bit_field_v41,
    it.prep_on,
    it.From_locn,
    it.Trans_to_locn,
    it.PDate,
    it.FirstDate,
    it.PTimeH,
    it.PTimeM,
    it.RetnDate,
    it.BookDate,
    it.TimeBookedH,
    it.TimeBookedM,
    it.TimeBookedS,
    it.del_time_hour,
    it.del_time_min,
    it.return_to_locn,
    it.return_time_hour,
    it.return_time_min,
    it.AssignTo,
    it.AssignType,
    it.InRack
FROM dbo.tblItemTran AS it
JOIN dbo.tblBookings AS tb ON
    tb.booking_no = it.booking_no_v32
WHERE
    (
        it.trans_type_v41 NOT IN (2, 3, 7, 18, 19, 20, 21, 12, 13, 22)
        AND it.trans_type_v41 NOT IN (6, 7)
        AND it.bit_field_v41 & CONVERT(tinyint, 4) = 0
    )
    OR
    (
        it.trans_type_v41 NOT IN (6, 7)
        AND it.bit_field_v41 & CONVERT(tinyint, 4) = 0
        AND tb.BookingProgressStatus = 1
    )
    OR 
    (
        it.trans_type_v41 IN (6, 7)
        AND it.bit_field_v41 & CONVERT(tinyint, 4) = 0
        AND it.QtyCheckedOut = 0
    )
    OR 
    (
        it.trans_type_v41 IN (6, 7)
        AND it.bit_field_v41 & CONVERT(tinyint, 4) = 0
        AND it.QtyCheckedOut > 0
        AND it.trans_qty - (it.QtyCheckedOut - it.QtyReturned) > 0
    );
GO
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.V1 (product_code_v42, ID);
GO

Mevcut görünüm yukarıdaki dizine alınmış görünümü kullanmak için ince ayarlanmış:

CREATE VIEW [dbo].[vwReallySlowView2]
AS
SELECT
    I.booking_no_v32 AS bkno,
    I.trans_type_v41 AS trantype,
    B.Assigned_to_v61 AS Assignbk,
    B.order_date AS dateo,
    B.HourBooked AS HBooked,
    B.MinBooked AS MBooked,
    B.SecBooked AS SBooked,
    I.prep_on AS Pon,
    I.From_locn AS Flocn,
    I.Trans_to_locn AS TTlocn,
    CASE I.prep_on 
        WHEN 'Y' THEN I.PDate
        ELSE I.FirstDate
    END AS PrDate,
    I.PTimeH AS PrTimeH,
    I.PTimeM AS PrTimeM,
    CASE
        WHEN I.RetnDate < I.FirstDate 
        THEN I.FirstDate 
        ELSE I.RetnDate
    END AS RDatev,
    I.bit_field_v41 AS bitField,
    I.FirstDate AS FDatev,
    I.BookDate AS DBooked,
    I.TimeBookedH AS TBookH,
    I.TimeBookedM AS TBookM,
    I.TimeBookedS AS TBookS,
    I.del_time_hour AS dth,
    I.del_time_min AS dtm,
    I.return_to_locn AS rtlocn,
    I.return_time_hour AS rth,
    I.return_time_min AS rtm,
    CASE
        WHEN
            I.Trans_type_v41 IN (6, 7) 
            AND I.Trans_qty < I.QtyCheckedOut
            THEN 0 
        WHEN
            I.Trans_type_v41 IN (6, 7)
            AND I.Trans_qty >= I.QtyCheckedOut
            THEN I.Trans_Qty - I.QtyCheckedOut
        ELSE
            I.trans_qty
    END AS trqty,
    CASE
        WHEN I.Trans_type_v41 IN (6, 7)
        THEN 0
        ELSE I.QtyCheckedOut
    END AS MyQtycheckedout,
    CASE
        WHEN I.Trans_type_v41 IN (6, 7)
        THEN 0
        ELSE I.QtyReturned
    END AS retqty,
    I.ID,
    B.BookingProgressStatus AS bkProg,
    I.product_code_v42,
    I.return_to_locn,
    I.AssignTo,
    I.AssignType,
    I.QtyReserved,
    B.DeprepOn,
    CASE B.DeprepOn
        WHEN 1 THEN B.DeprepDateTime
        ELSE I.RetnDate
    END AS DeprepDateTime,
    I.InRack
FROM dbo.V1 AS I WITH (NOEXPAND)
JOIN dbo.tblbookings AS B ON
    B.booking_no = I.booking_no_v32
JOIN dbo.tblInvmas AS M ON
    I.product_code_v42 = M.product_code;

Örnek sorgu ve uygulama planı:

SELECT
    vrsv.*
FROM dbo.vwReallySlowView2 AS vrsv
WHERE vrsv.product_code_v42 = 'M10BOLT';

Yeni uygulama planı

Yeni planda, karma maç var hiçbir kalıntı yüklemi yoktur, hiçbir kompleks filtre , hiçbir kalıntı yüklem dizinli görünüm aramak üzerine ve kardinalite tahminleri aynen doğrudur.

Ekleme / güncelleme / silme planlarının nasıl etkilendiğinin bir örneği olarak, ItemTrans tablosuna eklemenin planı şudur:

Plan ekle

Vurgulanan bölüm, endekslenmiş görünüm bakımı için yeni ve gereklidir. Tablo makarası, indekslenmiş görünüm bakımı için eklenen taban tablo satırlarını tekrar eder. Her satır kümelenmiş bir dizin araması kullanılarak rezervasyon tablosuna birleştirilir, ardından bir filtre WHEREsatırın görünüme eklenmesi gerekip gerekmediğini görmek için karmaşık cümle tahminlerini uygular . Öyleyse, görünümün kümelenmiş dizinine bir ekleme gerçekleştirilir.

Aynı SELECT * FROM viewtest daha önce 150ms'de tamamlandı ve endekslenmiş görünüm mevcuttu.

Son şey: 2008 R2 sunucunuzun hala RTM'de olduğunu fark ettim. Performans sorunlarınızı çözmez, ancak 2008 R2 için Service Pack 2 Temmuz 2012'den beri kullanılabilir durumdadır ve hizmet paketleriyle mümkün olduğunca güncel kalmanız için birçok iyi neden vardır.

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.