Önceden hızlı bir SQL sorgusu yavaş çalışmaya başladığında, sorunun kaynağını nerede bulabilirim?


36

Arka fon

Katılan ve / veya yaklaşık 12 farklı "tablo" sola katılan SQL Server 2008 R2 karşı çalışan bir sorgu var. Veritabanında 50 milyondan fazla satır ve yaklaşık 300 farklı tablodan oluşan birçok tablo bulunmaktadır. Ülke genelinde 10 depoya sahip büyük bir şirket için. Bütün depolar veri tabanına okuyor ve yazıyor. Bu yüzden oldukça büyük ve oldukça meşgul.

Sorun yaşıyorum sorgusu şuna benzer:

select t1.something, t2.something, etc.
from Table1 t1
    inner join Table2 t2 on t1.id = t2.t1id
    left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
    [etc]...
where t1.something = 123

Katılmalardan birinin korelasyonsuz bir alt sorguda olduğuna dikkat edin.

Sorun şu ki, bu sabah başlamak, sistemde herhangi bir değişiklik yapmadan (benim veya ekibimdeki herkesin bildiği gibi), genellikle yaklaşık 2 dakika süren, çalıştırmak için bir buçuk saat süren sorgu - hiç koştum. Veritabanının geri kalanı sadece iyi boyunca uğultu yapıyor. Bu sorguyu genellikle çalıştığı sproc'tan çıkardım ve aynı yavaşlıkta SSMS w / sabit kodlanmış parametre değişkenlerinde çalıştırdım.

Tuhaflık, ilişkili olmayan alt sorguyu alıp, geçici bir tabloya atıp alt sorgunun yerine kullandığımda sorgunun iyi çalıştığıdır. Ayrıca (ve bu benim için garip) bu kod parçasını sorgunun sonuna eklersem, sorgu harika çalışır:

and t.name like '%'

Yavaşlama sebebinin, SQL'in önbelleğe alınmış yürütme planının nasıl oluşturulduğuna bağlı olduğuna dair bu küçük deneylerden (belki de yanlış) karar verdim - sorgu biraz farklı olduğunda, yeni bir yürütme planı oluşturmak zorundadır.

Sorum şu: Hızlıca çalışan bir sorgu aniden yavaş yavaş yayınlanmaya başladığında ve bu sorgunun dışında başka hiçbir şey etkilenmiyorsa, nasıl sorun giderebilirim ve gelecekte nasıl olmasını engelleyebilirim ? SQL'in bu kadar yavaş hale getirmek için dahili olarak ne yaptığını nasıl bilebilirim (kötü bir sorgu çalıştırılırsa, yürütme planını alabilirim ancak çalışmayacak - belki de beklenen yürütme planı bana bir şey verebilir mi?)? Bu sorun yürütme planındaysa, SQL'in gerçekten berbat yürütme planlarının iyi bir fikir olduğunu düşünmesini nasıl önleyebilirim?

Ayrıca, bu parametre koklama ile ilgili bir sorun değildir. Bunu daha önce görmüştüm ve bu o değil, çünkü SSMS'deki değişkenleri kodladığımda bile performansım yavaşlıyor.


Sorgu planını (yavaş olanı) burada paylaşır mısınız
MJH

Yanıtlar:


31

Hızlı çalışan bir sorgu aniden gecenin ortasında yavaşça çalışmaya başladığında ve bu sorgu dışında başka hiçbir şey etkilenmezse, nasıl giderebilirim?

Yürütme planının hala önbellekte olup olmadığını kontrol ederek başlayabilirsiniz. Kontrol sys.dm_exec_query_stats, sys.dm_exec_procedure_statsve sys.dm_exec_cached_plans. Kötü yürütme planı hala önbelleğe alınmışsa, onu analiz edebilir ve yürütme istatistiklerini de kontrol edebilirsiniz. Yürütme istatistikleri, mantıksal okumalar, CPU zamanı ve yürütme zamanı gibi bilgileri içerecektir. Bunlar, sorunun ne olduğuna dair güçlü göstergeler verebilir (örneğin, büyük tarama ve engelleme gibi). Verilerin nasıl yorumlanacağına dair bir açıklama için bkz. Sorun sorgularını belirleme .

Ayrıca, bu parametre koklama ile ilgili bir sorun değildir. Bunu daha önce görmüştüm ve bu o değil, çünkü SSMS'deki değişkenleri kodladığımda bile performansım yavaşlıyor.

İkna olmadım. SSMS'deki sabit kodlama değişkenleri, geçmiş kötü yürütme planının çarpık bir girdiye karşı derlenmediğini kanıtlamaz. Konuyla ilgili çok iyi bir makale için lütfen Parametre Koklama, Gömme ve TAVSİYE Seçenekleri'ni okuyun . Uygulamada Yavaş, SSMS'de Hızlı? Performans Gizemlerini anlamak bir başka mükemmel referanstır.

Yavaşlama sebebinin, SQL'in önbelleğe alınmış yürütme planının nasıl oluşturulduğuna bağlı olduğuna dair bu küçük deneylerden (belki de yanlış) karar verdim - sorgu biraz farklı olduğunda, yeni bir yürütme planı oluşturmak zorundadır.

Bu kolayca test edilebilir. SET STATISTICS TIME ONderleme ile yürütme zamanını gösterir. SQL Server: İstatistik performans sayaçları aynı zamanda derlemenin bir sorun olup olmadığını da ortaya çıkaracaktır (açıkçası bunu pek olası bulmuyorum).

Ancak, vurabileceğiniz benzer bir şey var: sorgu hibe kapısı. Ayrıntılar için SQL server memory grant'ı anlama konusunu okuyun . Sorgunuz şu anda büyük miktarda bir hibe isterse, hiçbir bellek kullanılamaz, beklemek zorunda kalacak ve hepsi uygulamaya 'yavaş yürütme' olarak görünecektir. Bekleme bilgisi istatistiklerinin analiz edilmesi durum böyle olduğunda ortaya çıkacaktır.

Neyin ölçülüp neyin aranacağıyla ilgili daha genel bir tartışma için, bkz. SQL Server performansını nasıl analiz edersiniz.


7

Bu, SQL Server'da karmaşık sorgular çalıştırmanın bir cilvesidir. Neyse ki, o kadar sık ​​olmaz.

Sorgu için sorgu planına bakın (yavaş çalışıyorsa). Birleştirme işlemi için indeks içermeyen tablolarda bir veya daha fazla defa meydana gelen iç içe geçmiş bir döngü birleşimi bulacağınızı tahmin ediyorum. Bu gerçekten işleri yavaşlatıyor. Hızlı ileri sarmak için, bunu düzeltmenin bir ipucu var. Sorgunun sonuna aşağıdakini ekleyin:

OPTION (MERGE JOIN, HASH JOIN)

Bu genellikle geçmişte benim için bu sorunu çözdü.

Olanlar, masadaki (veya geçici boşluğun kullanılabilirliği) yapılan ince değişikliklerin, SQL optimizasyonunun daha yavaş bir birleştirme algoritması tercih etmesine neden olmasıdır. Bu oldukça ince ve ani olabilir. Geçici bir tablo oluşturduğunuzda, optimize edici tablo hakkında daha fazla bilgiye sahiptir (büyüklüğü gibi), böylece daha iyi bir plan oluşturabilir.


1
Uygulama planı aslında iç içe geçmiş bir döngü birleşimini kullanıyor. Ancak, ipucunu önerdiğiniz gibi yerleştirdiğimde şu hatayı alıyorum: "Sorgu işlemcisi, bu sorguda tanımlanan ipuçları nedeniyle bir sorgu planı oluşturamadı. Herhangi bir ipucu belirtmeden ve SET FORCEPLAN kullanmadan sorguyu yeniden gönderin." OPTION (LOOP JOIN) tabiki eklediğimde, bir yürütme planı oluşturacak, ancak hala yavaş çalışmasıyla ilgili bir sorunum var. Bu sorunla karşılaştınız mı? Katılmaya ihtiyaç duyulduğunu düşünüyor gibi görünüyor.

@Trevor. . . Hayır bu sorunu gerçekten görmedim. Belki de sorgunuz bazı equijoins yapmıyor (eşit işaretler kullanmıyorsunuz) ve optimizer orada iç içe döngü birleşimleri kullanmak zorunda.
Gordon Linoff

3

Genellikle bu tür sorunlara neden olan eksik bir endeks var.

Genelde yaptığım şey, SQL Management Studio'yu kullanarak sorguyu çalıştırmak ve 'Gerçek Yürütme Planını Dahil Et (CTRL + M)' özelliğini etkinleştirmek ve hangisinin en büyük yüzdeye sahip olduğunu bulmak.

Uygulama tıkanıklığı üzerinde durmuyor, ancak sadece sonuç bakarak "hızlı" bulabilirsiniz.

burada örnek: 48PercentForTop


2
bir endeks birdenbire “kaybolmaz”, yani bu performansı iyileştirebilirken sorunu açıklamıyor
Fowl

3

Geçenlerde, beni bu sayfaya getiren aynı sorunu yaşadım.

@MartinSmith istatistiklerinizi güncellemenizi ve planınızı açıklamanızı önerdiğinde bir şeydeydi. Ayrıca kilit oluşturabilecek işlere / sorgulara göz atmanızı ve böylece yanıt süresini yavaşlamanızı sağlamaya çalışmanız gerektiğini de eklemek isterim.

Benim durumumda suçlu, masa toplama işi toplama işiydi. Bazı nedenlerden dolayı, sahip olması gereken pencerede tamamlamadı ve kullanıcılar devam ettiğinde çalışmaya devam etti. Süreci buldum, öldürdüm ve sorgular tekrar cevap vermeye başladı.

Umarım bunun bir başkasına yardımı olur


0

Ayrıca T-SQL \ Prosedüründeki performans sorununu gördüğünüzde herhangi bir sunucu yedeklemesi veya herhangi bir Arşivleme \ dizin oluşturma işinin çalışıp çalışmadığını kontrol etmeniz gerekir.

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.