Bir uygulamada yavaşlamaları teşhis etmeye çalışıyorum. Bunun için SQL Server genişletilmiş olayları günlüğe kaydettim .
- Bu soru için belirli bir saklı yordam bakıyorum.
- Ancak, bir elmadan elmaya araştırma olarak eşit olarak kullanılabilecek bir düzine saklı yordam seti vardır.
- ve saklı yordamlardan birini el ile çalıştırdığımda, her zaman hızlı çalışır
- ve bir kullanıcı tekrar denerse: hızlı çalışır.
Saklı yordamın yürütme süreleri çok değişkendir. Bu saklı yordamın birçok yürütme <1s içinde döner:
Ve bu "hızlı" kova için, 1 saniyeden çok daha az. Aslında 90 ms civarında:
Ancak 2s, 3s, 4s saniye beklemek zorunda olan uzun bir kullanıcı kuyruğu var. Bazıları 12s, 13s, 14s beklemek zorunda. Sonra 22'ler, 23'ler, 24'ler beklemek zorunda olan gerçekten fakir ruhlar var.
Ve 30 saniye sonra, istemci uygulaması pes eder, sorguyu iptal eder ve kullanıcı 30 saniye beklemek zorunda kaldı .
Nedeni bulmak için korelasyon
Bu yüzden ilişkilendirmeye çalıştım:
- süre vs mantıksal okumalar
- fiziksel okumalara karşı süre
- süre vs işlemci süresi
Ve hiçbiri herhangi bir korelasyon vermiyor gibi görünmüyor; hiçbiri neden gibi görünmüyor
süre mantıksal okumalara göre : ister biraz ister mantıksal okuma olsun, süre hala çılgınca dalgalanıyor :
süresi ve fiziksel okumalar : sorgu önbellekten sunulmamış olsa ve çok fazla fiziksel okumaya ihtiyaç duyulsa bile, süreyi etkilemez:
süresi vs cpu süresi : Sorgunun 0s CPU zamanı mı yoksa 2.5s CPU zamanı mı aldığı, süreler aynı değişkenliğe sahiptir:
Bonus : Süre v Fiziksel Okumalar ve Süre v CPU saatinin çok benzer göründüğünü fark ettim . CPU zamanını fiziksel okumalarla ilişkilendirmeye çalışırsam bu kanıtlanmıştır:
G / Ç'den çok fazla CPU kullanımı olduğu ortaya çıkıyor. Kim biliyordu!
Peki , yürütme süresindeki farklılıkları açıklayabilecek sorguyu yürütme eylemi hakkında hiçbir şey yoksa, bunun CPU veya sabit sürücü ile ilgisi olmadığı anlamına mı geliyor?
CPU veya sabit sürücü darboğazdaysa; darboğaz olmaz mıydı?
Darboğazın CPU olduğunu varsayarsak; CPU'nun bu sunucu için yetersiz olduğundan:
- daha fazla CPU zamanı kullanan yürütmeler daha uzun sürmez mi?
- aşırı CPU kullanarak başkaları ile tamamlamak zorunda beri?
Sabit sürücüler için de benzer şekilde. Sabit sürücünün bir darboğaz olduğunu varsayarsak; sabit sürücülerin bu sunucu için yeterli rasgele geçişe sahip olmadığı:
- daha fazla fiziksel okuma kullanan yürütmeler daha uzun sürmez mi?
- aşırı yüklenmiş sabit sürücü G / Ç kullanarak başkaları ile tamamlamak zorunda çünkü?
Saklı yordamın kendisi herhangi bir yazma işlemi gerçekleştirmez veya gerektirmez.
- Genellikle 0 satır (% 90) döndürür.
- Bazen 1 satır (% 7) döndürür.
- Nadiren 2 satır (% 1.4) döndürür.
- Ve en kötü durumlarda 2'den fazla satır döndürdü (bir kez 12 satır döndürüyor)
Yani çılgınca bir veri hacmi döndürüyor gibi değil.
Sunucu CPU Kullanımı
Sunucunun İşlemci Kullanımı yaklaşık% 1.8, ara sıra% 18'e varan bir artışla ortalama CPU yükü bir sorun gibi görünmüyor:
Yani sunucu CPU aşırı yüklü görünmüyor.
Ama sunucu olan sanal ...
Evrenin dışında bir şey mi var?
Hayal edebileceğim tek şey, sunucunun evreninin dışında var olan bir şey.
- mantıklı değilse
- ve fiziksel okumalar değil
- ve cpu kullanımı değil
- ve CPU yükü değil
Ve saklı yordamın parametreleri gibi değil (çünkü aynı sorguyu elle yayınlamak ve 27 saniye sürmez - ~ 0 saniye sürer).
Başka bir şey, aynı derlenmiş saklı yordamı çalıştırmak için bazen 0 saniye yerine 30 saniye süren sunucuyu açıklayabilir.
- kontrol noktaları?
Sanal bir sunucudur
- Ev sahibi aşırı yüklendi mi?
- Aynı ana bilgisayardaki başka bir VM?
Sunucunun genişletilmiş olaylarını gözden geçirme; bir sorgu aniden 20 saniye sürdüğünde özellikle başka bir şey olmaz. İyi çalışır, sonra iyi çalışmaya karar verir:
- 2 saniye
- 1 saniye
- 30 saniye
- 3 saniye
- 2 saniye
Ve bulabileceğim, özellikle yorucu bir şey yok. Her 2 saatlik işlem günlüğü yedeklemesi sırasında değil.
Başka ne olabilir ki ?
"Sunucu" dışında söyleyebileceğim bir şey var mı ?
Düzenleme : Günün saatine göre ilişkilendir
Süreleri her şeyle ilişkilendirdiğimi fark ettim:
- mantıksal okumalar
- fiziksel okumalar
- CPU kullanımı
Ama ilişkilendirmediğim tek şey günün zamanı idi . Belki her-2 saatlik işlem günlük yedekleme olan bir sorun.
Ya da belki yavaşlamalar do kontrol noktalarında sırasında atıyormuş meydana?
Hayır:
Intel Xeon Gold Dört Çekirdekli 6142.
Düzenle - Kişiler sorgu yürütme planını varsayıyor
İnsanlar sorgu yürütme planlarının "hızlı" ve "yavaş" arasında farklı olması gerektiğini varsaymaktadır. Onlar değil.
Ve bunu incelemeden hemen görebiliriz.
Uzun soru süresinin "kötü" bir yürütme planı nedeniyle olmadığını biliyoruz:
- daha mantıklı okumalar alan
- daha fazla birleşim ve anahtar aramalardan daha fazla CPU tüketen
Çünkü okumalardaki bir artış veya CPU'daki artış, sorgu süresinin artmasının bir nedeni olsaydı, bunu daha önce görmüş olabilirdik. Hiçbir korelasyon yoktur.
Ancak, süreyi CPU-okuma alanı ürün metriğiyle ilişkilendirmeye çalışalım:
Daha az bir korelasyon olur - bu bir paradokstur.
Düzenleme : Çok sayıda değer içeren Excel dağılım grafiklerinde bir hatayı gidermek için dağılım diyagramları güncelleştirildi.
Sonraki adımlar
Bir sonraki adımım, 5 saniye sonra birisinin engellenen sorgular için etkinlik oluşturması için sunucuya sahip olmak olacak :
EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE
Sorguların 4 saniye boyunca engellenip engellenmediğini açıklamaz . Ama belki bir sorguyu 5 saniye boyunca engelleyen her şey de 4 saniye boyunca bazılarını engeller.
Yavaş Planlar
Yürütülen iki saklı yordamın yavaş planı:
- `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'
- `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'
Aynı parametrelerle aynı saklı yordam, arka arkaya çalışır:
| Duration (us) | CPU time (us) | Logical reads | Physical reads |
|---------------|---------------|---------------|----------------|
| 13,984,446 | 47,000 | 5,110 | 771 |
| 4,603,566 | 47,000 | 5,126 | 740 |
Çağrı 1:
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
|--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
| | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
| | | |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
| | |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
| |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]), WHERE:([Contos
|--Filter(WHERE:([Expr1009]>(1)))
|--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
|--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC
Çağrı 2
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
|--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
| | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
| | | |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
| | |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
| |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]), WHERE:([Contos
|--Filter(WHERE:([Expr1009]>(1)))
|--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
|--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC
Planların aynı olması mantıklıdır; aynı parametrelerle aynı saklı yordamı yürütüyor.