SQL sunucusunda yüksek CPU kullanımı - Yavaş sorgular [kapalı]


11

MS SQL Server'ımız CPU gücünün yaklaşık% 95'ini kullanıyor.

Bir sunucu (donanım) yeniden başlatıldıktan veya SQL Hizmeti yeniden başlatıldıktan sonra kullanım% 0 olur ve 1-3 gün boyunca yavaş yavaş artar. Ne kadar kullanıldığına bağlı olarak.

% 80'in üzerinde olduğunda, her sorgu son derece yavaştır.

Web sitemiz çok sayıda büyük sorgu ile uğraşmaktadır, bu nedenle bazıları 45-60 saniye sürmektedir. Yeniden başlatmadan sonra (CPU kullanımı% 80'den az), aynı Sorgu için 11-20 saniye sürer.


Bunu nasıl düzeltebilirim? Çevrimiçi olarak afinite maskelerinin CPU kullanımını ayarlayabildiğini, ancak Afinite ayarlarının devre dışı bırakıldığını okudum. Onları değiştiremem. Bu sadece 1 işlemcim olduğu için mi?

Sorguların kendileri ile ilgili birçok püf noktası var, ancak web sitelerimiz ve hizmetlerimiz oldukça büyük ve değiştirmek için çok fazla şey var.

Çoğu zaten oldukça iyi optimize edilmiş.


Sadece 2 saniye sürse de SQL-Service'i yeniden başlatamıyorum, çünkü insanların aramasına ve bir mesaj kaydetmesine izin veren bir alarm servisimiz var, seçilen bir grup daha sonra çağrılacak ve kaydedilen mesajı duyacaktır.

Bu sistem yüzlerce Arama Kurtarma ekibi tarafından kullanılır ve bir alarm sırasında SQL-Service yeniden başlatılırsa, sonlandırılır ve onu arayan kişiye bildirim gönderilmez.


Her yerde arama yaptım, ancak değiştiremediğim "Afinite Maskeleri" ile ilgili şeyler dışında hiçbir şey bulamadım.

Mevcut sorguları sonlandırmadan CPU önbelleğini temizlemenin bir yolu olmalı ... değil mi?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB

Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Paul White 9

Yanıtlar:


7

Bu uzun bir atış, ancak zorunlu parametrelendirme ayarınıza bir göz atmak isteyebilirsiniz. Performans kötü olduğunda çok sayıda sorgu planı görüyorsanız, sorgularınız beklediğiniz şekilde önbelleğe alınmaz ve sorguların zaten kullanmak için bir plan olup olmadığını görmek için önbellek taraması uzun zaman alıyor. Önbelleği temizlemek bu sorunu çözerse, zorunlu parametreleştirme ayarını değiştirmek isteyebilirsiniz. Önbelleği aşağıdakileri kullanarak temizleyebilirsiniz:

DBCC FREEPROCCACHE

Önbellek temizlendiğinde çalıştığında zorunlu parametreleştirme ayarının ne olduğunu kontrol edebilirsiniz:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Bu, varsayılan olarak muhtemelen 0 olarak ayarlanmıştır. Eğer arzu ederse, bunu yaparak doğru olarak ayarlayabilirsiniz:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Bu, önce geliştirici ortamında yapılmalıdır ve bunun veritabanını başka şekillerde olumsuz etkileyip etkilemediğine bakın. Aşağıdakiler kullanılarak döndürülebilir:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;

5
Yordam önbelleği boşaltmanın aslında CPU'da büyük bir artışa neden olabileceğini unutmayın - çünkü tüm sorgular artık yürütme planlarını yeniden derlemek zorunda kalacaktır.
Aaron Bertrand

18

Afinite "CPU kullanımını ayarlamaz" (örneğin, durumda CPU'ların daha az iş yapmasını sağlar), bir CPU'yu kapatmanıza (belki de aynı makinedeki başka bir örnek için kullanılabilir hale getirmenize) veya CPU'yu yalnızca G / Ç ile yardım. Birden fazla CPU'nuz olsa bile, hedefinize yardımcı olması için ilkini kullanamazsınız ve ikincisini tahmin etmemiz imkansızdır çünkü CPU kullanımınızı neyin bu kadar yüksek yaptığını bilmiyoruz. Son derece zayıf indeksleme, aşırı derlemeler, skaler UDF'lerin bolluğu, I / O thrashing, kim bilir biliyor? (Ve I / O'nun nedeni olabilmesinin nedeni, veritabanınız 3 GB veya daha büyükse, sürekli olarak arabellek havuzu belleğine girip çıkması gerektiğidir ve bu da CPU'ya zarar verir.)

CPU önbelleği de aşağı inmenize gerek olmayan bir tavşan deliğidir. CPU önbelleğinizle ilgili sorunlar nedeniyle CPU'nuzun% 95 oranında çöktüğünden şüpheleniyorum.

CPU baskısının kaynağını daraltmanıza ve saklı yordamları kullandığınızı varsayarsak, bu tanılama sorgusuna Glenn Berry'den ( buradan kaynaklanır ) göz atabilirsiniz - doğru veritabanı bağlamında çalıştırdığınızdan emin olun:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

SELECT TOP (25) 
  p.name AS [SP Name], 
  qs.total_worker_time AS [TotalWorkerTime], 
  qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], 
  qs.execution_count, 
  ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) 
    AS [Calls/Second],
  qs.total_elapsed_time, 
  qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time], 
  qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

Saklı yordamlar kullanmıyorsanız, John Samson'un bu örneği geçici sorguları ( buradan kaynaklanır ) izole etmeye yardımcı olabilir :

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

Ayrıca , şu anda çalışan tüm sorguları hızlı bir şekilde analiz edebilen ve istediğiniz gibi sıralamanıza izin veren saklı bir prosedür olan Adam Machanic'in sp_WhoIsActive'ine bir göz atabilirsiniz@sort_order = '[CPU] DESC' .

İlk yapacağım şey - özellikle de bu gerçekten arama ve kurtarma ekipleri için kritik bir görevse - daha iyi bir donanım satın almak. Uygulamanıza hizmet vermek için daha fazla CPU'nuz ve daha fazla RAM'iniz olmalıdır. Ayrıca kesinlikle daha iyi yüksek kullanılabilirliğe ihtiyacınız vardır (örneğin kümeleme, yansıtma veya Kullanılabilirlik Grupları). Fiziksel bir makinenin yeniden başlatılmasının uygulamanızı tamamen çevrimdışına almasının bir nedeni yoktur - bu sorun için daha iyi çözümlerimiz var. Ve son olarak, bu "sunucu" sadece bir spinny disk sürücüsü olduğunu varsayalım. Bu, işletim sisteminden, SQL Server veri dosyalarından, günlük dosyalarından, tempdb vb. Gelen tüm G / Ç'nin tek bir denetleyiciden geçtiği ve okuma / yazma etkinliğini tek bir sürücüde paylaştığı anlamına gelir. Daha fazla disk alın. Mümkünse / varsa SSD'leri alın. RAID kullanın ve G / Ç'yi mümkün olduğunca yaymaya çalışın.

Tüm bunların söylendiği gibi, donanımın problemi atması düzeltmenin tek parçası olmayacak. Aşırı CPU kullanımına neyin sebep olduğunu tam olarak yalıtmanız ve ardından hangi donanımda olursanız olun bu sorunlara saldırmanız gerekir.

Diğer bazı fikirler için şu StackOverflow sorusuna da bakın:

/programming/945063/how-do-i-find-out-what-is-hammering-my-sql-server


0

Aşağıdaki öneriler 'karanlıkta bir atış' çünkü gerçek kodu göremiyorum.

Birincisi, bir SP imleçleri açıyor ve açık bırakıyor olabilir. İmleçler, özellikle Close ve Deallocate hakkında bilgi edinin. Birisi kapanıyor olabilir ama imleçleri dağıtmıyor olabilir. Yükseltme nedeniyle davranış değişmiş olabilir, 2012 artık imleçlere 2008 R2'den farklı davranabilir.

İkincisi, temizlenmeyen masa kilitleri olabilir. Yine, ben uzaktayım, bu yüzden söyleyemem, ama birinin 'işlem başlat' sonrasında küresel bir geçici tablo oluşturduğunu ve 'son işlem' yürütülmediğini veya saklı yordamın kilitli kalmayı bırakmadığını gösterir tempdb yer işgal tablosu.

WinLink'i şans eseri mi kullanıyorsun? Bununla ilgili bir şey belirsiz görünüyor.


-4

Performansı artırmak için memcached gibi bir önbellekleme mekanizmanız olmalıdır.


Ancak bu, SQL Server'daki CPU kullanımını değiştirmez, değil mi? Bu sadece web sitesinde sorguları daha hızlı gitmek yapmak olacaktır ve başkaları aynı tablodan memcached sonuçları kullanırken, bir tabloda bir şey değişti sorun olabilir, değil mi?
Levi Johansen

@Levi, sorgu sonuçlarını orta katmanda bir yerde önbelleğe alırsanız, sorgular veritabanına çarpmaz (önbelleği yenilemeniz gerektiğinde).
Aaron Bertrand

1
Web sitesinde kimse olmadığında CPU da yüksekse, web düzeyinde şeyleri önbelleğe almak yardımcı olmaz. Memcached harika bir araçtır, ancak yetkili bir kişinin oturması ve sunucunun hiçbir şey yapmaması gerektiği zaman ne yaptığını öğrenmesi için bir yedek değildir.
TomTom
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.