Kod, saklı yordamda geçici olarak çalıştırıldığında farklı bir plan oluşturur


9

Saklı yordam içinde çalıştırırken kötü bir plan kullanan, ancak geçici çalıştırırken çok daha iyi bir plan seçiyor bir silme ifadesi var.

Ben sorgu tarafından kullanılan tablolar için tüm dizinleri yeniden var ve tüm önbellekleri düştü. Optimize edici, saklı yordam için hala yanlış planı seçer.

İyileştiricinin neden geçici SQL'e karşı saklı yordam için farklı bir yürütme planı kullandığını bilmek istiyorum.

GÜNCELLEME: Sanırım sonuçta parametreleri olmalıydı - ad-hoc kodunu sabit kodlu değişkenle çalıştırdığımda, doğru değerle "kötü" planı alabilirim (bir tarih, bir yaşında olan değerler) "iyi" planı oluşturuyor gibi görünüyor). Şimdi bir sorgu ipucu kullanarak proc "iyi" planı zorlamaya çalışıyor.

ÇÖZÜM: BİLİNMİYOR İPUCU ipucunu kullanarak istediğim planı elde ettim.


Muhtemelen parametre koklamasıdır . Sorgu, WHEREcümlesindeki bir değişkene başvuruyor mu?
Nick Chammas

4
Lütfen kodu ekleyebilir misiniz
gbn

Ayrıca planları bir yere gönderin lütfen. Olduğu gibi, planların neden farklı olduğunu size söylemek oldukça zor olacak.
Aaron Bertrand

Tamam, daha fazla bilgi: Planları ve kodları biraz gizleyene kadar gönderemiyorum. Birkaç dakika içinde onları kaldırmaya çalışacağım. Saklı yordamın planı (kötü) büyük bir tablonun (tüm şey, tüm bölümler) kümelenmiş bir dizin taraması yapar. Daha sonra, daha küçük bir tablodaki satırları bulmak için bir döngü kullanır ve sonra daha küçük tablodan siler.
msgisme

Geçici kod (iyi) planı, küçük tablonun tablo taramasını yapar (yalnızca 5-10 satırı vardır) ve PK'da hangi satırları kontrol etmesi gerektiğini bulmak için büyük tablonun kümelenmemiş bir dizinini kullanır büyük tablo. En kısa sürede gerçek planları hazırlamaya çalışacağım.
msgisme

Yanıtlar:


5

Olağan Şüpheliler:

  1. adhoc sabitleri, kod parametreleri
  2. koddaki veri türlerinin uyumsuzluğu
  3. parametre koklama

Nokta 1: iyileştirici sabitler için en iyi planı seçebilir.
Sabitleri değiştir = planı değiştir. Parametreli bir plen resuable

Nokta 2 veri türü önceliği nedeniyle örtük dönüşümler getirecektir,
örneğin nvarchar parametresine kıyasla varchar sütunu

Nokta 3: parametre maskeleme kullanın veya BİLİNMEYENLER İÇİN OPTİMİZE EDİNİN
Düzenle: Test etmek için: saklanan proc'u çalıştırın, sp_updatestats'ı çalıştırın, tekrar çalıştırın. Bu, önbellek planlarını geçersiz kılacaktır; bu, plan önbelleğini temizlemekten daha iyidir

Edit: jcolebrand'ın yorumundan sonra

Koklamayı birkaç şekilde devre dışı bırakabilirsiniz. Ana 3

  • RECOMPILE. Bu aptalca IMO.
  • BİLİNMEYENLER İÇİN OPTİMİZE EDİN
  • Parametre maskeleme

Parametre maskeleme:

DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam

SELECT...WHERE column = @MaskedParam

Maskeleme ve OPTIMIZE ipucu aynı etkiye sahiptir (belki farklı nedenlerle). Yani, optimize edici istatistik ve veri dağıtımını kullanmak zorundadır ( Not: Mark Storey-Smith tarafından test altındadır ) parametreleri kendi değerlerine göre değerlendirir mi? son çağrıdan çok. Optimize edici yeniden derlenebilir veya olmayabilir. SQL Server 2005, daha az etki olması için deyim düzeyi yeniden derlemesi ekledi

Şimdi, neden "sniffed" parametreleri ile bir plan "yapışkan" maskeli / "bilinmeyen" parametreleri ile karşılaştırıldığında, emin değilim.

SQL Server 2000'den bu yana en basit kod hariç tüm parametre maskelemesini kullandım. Ben daha karmaşık kod ile gerçekleşmek sorumlu olduğunu kaydetti. Ve eski işimde plan parametresi varsayılanlarını değiştirebileceğim bazı raporlar var. "Kargo kült" yaklaşımının bir destek çağrısından daha kolay olduğunu düşünüyorum.

Düzenle 2, 12 Eki 2011, biraz sohbet ettikten sonra

  • Parametre maskeleme ve BİLİNMEYENLER İÇİN OPTİMİZE ET, söyleyebildiğim kadarıyla aynı etkiye sahiptir
    İpucu ipucu maskelemeden daha temizdir ancak SQL Server 2008 ile eklenmiştir.

  • Parametre koklaması derleme zamanında gerçekleşir.
    RECOMPILE İLE her yürütme yeni bir plan oluşturur. Bu, düşük bir varsayılan seçimin planı etkileyeceği anlamına gelir. Son işimde, bunu bazı rapor kodlarıyla kolayca gösterebilirim: parametre varsayılanlarını değiştirmek, sağlanan parametrelerden bağımsız olarak planı değiştirdi.

  • Bu MS Connect makalesi ilginç: Saklı yordam içinde yetersiz dizin kullanımı (aşağıdaki SO yanıtlarından birinde belirtilmiştir)

  • Bob Beauchemin de bundan bahsediyor

Öne çıkan sorunlar

  • RECOMPILE İLE koklama hala geçerli mi? Yani, eğer optimizer planı atmayı biliyorsa, yeniden kullanımı mı hedefliyor?

  • Koklanan planlar neden "yapışkan"?

SO'dan bağlantılar:


1. sp parametresi kod 2 bir değişkendir. Yine, aynı veri türü 3. Her ikisi de çok çeşitli parametreler ile çalıştım ve her seferinde aynı planı alıyorum. Her denemeden sonra önbelleği temizledim.
msgisme

1
Ynt: nokta 3. Ayrıca SQL Server varolan planları dikkate almaya zorlamak için deyimi OPTION (RECOMPILE)veya tüm proc çalıştırabilirsiniz WITH RECOMPILE.
Nick Chammas

3
BTW OPTIMIZE, çünkü Microsoft bir Amerikan şirketi. :)
Nick Chammas

1
@Gbn, parametre koklamanın önlenmesi / yenilmesi ile ilgili düşünceleriniz var mı?
jcolebrand

1
@jcolebrand: basit cevap "hayır" :-)
gbn

2

Bağlantı için ayarladığınız ANSI ayarlarının yürütme planı seçiminde bir rol planladığını unutmayın. Uygulama saklı yordamı çağırdığında, muhtemelen SSMS bağlantınızdan farklı ANSI ayarları 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.