Depolanmış Proc için Aniden Yavaş Uygulama Planı


15

SQL Server 2000 ile yaşadığımız bir sorunu anlamaya çalışıyorum. Biz orta derecede işlem yapan bir web sitesiyiz sp_GetCurrentTransactionsve bir customerID ve iki tarih kabul eden adlı bir saklı proc var .

Artık tarihlere ve müşteriye bağlı olarak, bu sorgu sıfırdan 1000 saniyeye kadar olan satırları döndürebilir.

Sorun: Yaşadığımız şey, birden bire Execution Timeout Expiredbelirli bir istemci için depolanan proc'u yürütmeye çalışırken bir takım hatalar (tipik olarak veya benzer) alacağımızdır . Bu yüzden sorguyu inceliyoruz, SSMS'de çalıştırıyoruz ve 30 saniye sürdüğünü buluyoruz. Bu yüzden depolanan proc'u yeniden derliyoruz ve -bang- şimdi 300ms'de çalışıyor.

Bu konuda DBA'mızla konuştum. Saklı işlemi yarattığımızda veritabanının bir sorgu planı oluşturduğunu söyledi. Bu parametre kümesi için iyi bir plan olduğunu söyledi, ancak belirli bir parametre kümesini atarsanız, plan bu veriler için en iyi plan olmayacaktır ve bu yüzden yavaş çalıştığını göreceksiniz.

Bana sunulan seçenekler, bu sorgu sorgusu depolanan bir proc ve geri her çalıştırmada oluşturulan yürütme planı olan dinamik SQL içine taşımadır.

Bu bana geri adım gibi geliyor ve bunun etrafında bir yol olması gerektiğini hissediyorum. Bu sorunla başa çıkmanın başka bir yolu var mı?

Her türlü yanıt takdir edilmektedir.


proc bir if / else deyimi var mı? Plan if deyiminde önbelleğe alındığında ve sonra yanlış planı kullanarak başka blok altında yürütmeye çalıştığında bu gördüm. Bu hatalar işlemdeki bir değişikliğe karşılık geldi mi?
Jeremy Gray

@Jeremy: Proc'ta değişiklik yok ve başka / if ifadeleri yok.
Ciaran Archer

Yanıtlar:


14

Bu soruna parametre koklama adı verilir.

SQL Server'ın sonraki sürümleri, onunla OPTION (RECOMPILE)veya OPTIMIZE FORipuçlarıyla ilgili olarak daha fazla seçenek sunar .

Saklı yordamda değişkenleri bildirmeyi, parametre değerlerini değişkenlere atamayı ve değişkenlerin yerine parametrelerin yerine, çoğu zaman makul düzeyde tatmin edici bir plan görüyormuş gibi kullanmayı deneyebilirsiniz.

Normalde en felaket açısından kötü planlar, çok yüksek seçiciliğe sahip, ancak düşük seçiciliğe sahip parametreler için derlenenlerdir.

Oluşturulan planın bu yaklaşımla daha sağlam ve tüm parametre değerleri için tatmin edici olduğunu varsayarsak, bu yaklaşımın JNK tarafından önerilene göre avantajı, her çağrı için bir derleme maliyeti oluşturmamasıdır.

Dezavantajı, bazı yürütmeler için çalışma süresinin, bu parametre değerleri için özel olarak hazırlanmış bir plandan daha büyük olabilmesidir, bu nedenle derleme zamanı ile yürütme zamanı arasındaki değiş tokuştur.


3
Veya Oracle terminolojisinde "bağlama"
Gaius

Teşekkürler @Gaius, birden fazla RDBMS için terminolojiyi bilmek iyi;)
Andrei Rînea

6

Dinamik SQL kullanmak yerine, proc çağrılarınızı her zaman şu şekilde değiştirebilirsiniz:

EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE

WITH RECOMPILEKuvvetler (bunu tahmin!) Çalıştırıldığı zaman yürütme planının bir recompile.

Ayrıca WITH RECOMPILE, saklanan proc tanımına da ekleyebilirsiniz :

CREATE PROCEDURE usp.MyProcedure (Parameters)
WITH RECOMPILE
AS
...

2

Ayrıca, kullanmayı planlayan veritabanına karar vermeyi de deneyebilirsiniz, ancak optimizer ile biraz kavga edersiniz, bu yüzden umduğunuzdan daha kırılgandır.

Teknik şudur - saklı prosedürü, biri bir parametre seti için, diğeri için olmak üzere 2'ye bölün. Aralarındaki tüm cümleleri, aralarındaki tüm olası durumları kapsayacak şekilde ekleyin. Sorgu planlarına bakın - biri parametre kümesi için diğeri diğeri için optimize edilmelidir. Bunun gerçekleşmesi için sorguyla uğraşmak zorunda kalabilirsiniz veya bu, sorgunuz için başarılması mümkün olmayabilir, bu durumda bu yaklaşım işe yaramaz.

Şimdi orijinal saklı yordamınızın parametre değerlerini kontrol etmesini sağlayın ve önceki paragrafta saklanan iki yordamdan uygun olanını gönderin.

Bu işe yarayabilir, ancak optimize ediciyi sorgunuz için daha etkili bir şekilde çalışmaya zorlamak bir tür hack'tir. Tüm bu hackler gibi, veritabanının gelecekteki sürümlerinde gereksiz olabilir, hatta işleri daha da kötüleştirebilir. Bu yüzden işe yarasa bile buna değip değmeyeceğine karar vermelisiniz.



0

Hmmm ... sadece bu saklı yordama odaklanırsak, önbelleğe alınmış yürütme planını kullanmanın gördüğünüz soruna neden olacağına şaşıracağım. Müşteri ve iki tarih için bir dizi parametre kullanarak saklı yordamın yürütme planını görmek isterim. Acaba daha spesifik bir dizin yararlı olur -> gibi customerId ve sadece iki tarih gibi?


2
Neden sürpriz? parametre koklama bu belirtilerle oldukça yaygın bir sorundur ve DBA bunu problem olarak tanımlamış gibi görünmektedir.
Martin Smith

@MartinSmith - Parametre kokusunu bilen DBA'nın yeniden derleme ipuçlarını bilmediği için biraz şaşırdım ...
JNK

@JNK - Bu doğru. Neden bahsetmediklerinden emin değilim.
Martin Smith

0

Aniden performans düşüşü, muhtemelen eksik istatistiklerin bir sonucu olarak üretilen verimsiz bir sorgu planı gibi geliyor. "Hatalar ve Uyarılar" olay kategorileri ayarlanmış bir SQL Server profili oluşturup eksik istatistiklerle ilgili uyarı olup olmadığını görün.

Bir dizini de kaçırıyor olabilir veya SQL Server'ın kullanamayacağı kadar parçalı olabileceğinden dizinleri birleştirmeniz gerekebilir, bu da bir Tablo Taramanın daha az G / Ç üreteceğini düşünerek sonuçlanır.

@JNK depolanmış procs hakkında büyük bir noktaya değinir - bunlar önceden derlenir ve sorgu planı saklı yordamla birlikte saklanır.

RECOMPILE İLE kullanmayı kesinlikle kabul etmiyorumDepolamak ve yeniden kullanılan sorgu planının yararını kaybettiğiniz için . Bunun gerekli olduğu bazı durumlar vardır - örn. Temel tablolardaki dağıtım istatistikleriniz çağrılar arasında büyük farklılıklar gösterirse, ancak genellikle, tablolardaki veriler olgunlaştıktan sonra tablolardaki verilerin dağılımı minimum düzeyde değişir.

Özetlemek gerekirse:

  1. Eksik istatistikleri kontrol edin
  2. Dizin parçalanmasını kontrol edin
  3. Depolanmış bir proc oluşturma ve kullanma
  4. Lütfen proc adını yeniden adlandırın - sp_, dahili sistem SQL Server procs için yumuşak bir şekilde ayrılmış önek ad alanıdır - bu, SQL Server'ın her zaman ilk saklanan yordamlar için ana veritabanına bakmasına neden olur. Sp_ yerine proc usp_ adını değiştirmek performans artışıyla sonuçlanır, ancak bu durumda sorununuzdan şüpheliyim.
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.