Wysokie użycie procesora na serwerze SQL - powolne zapytania [zamknięte]

11

Nasz MS SQL Server zużywa około 95% mocy procesora.

Po ponownym uruchomieniu serwera (sprzętu) lub ponownym uruchomieniu usługi SQL użycie wynosi 0% i powoli wzrasta w ciągu 1-3 dni. W zależności od tego, ile to jest używane.

Gdy wynosi ponad 80%, każde zapytanie jest bardzo wolne.

Nasza strona internetowa zajmuje się wieloma dużymi zapytaniami, więc niektóre z nich zajmują 45-60 sekund. Po ponownym uruchomieniu (zużycie procesora poniżej 80%), ta sama Kwerenda zajmuje 11-20 sekund.


Jak mogę to naprawić? Czytałem online, że maski koligacji mogą regulować użycie procesora, ale ustawienia koligacji są wyłączone. Nie mogę ich zmienić. Czy to dlatego, że mam tylko 1 procesor?

Istnieje wiele sztuczek związanych z samymi zapytaniami, ale nasze witryny i usługi są dość duże, a po prostu jest zbyt wiele do zmiany.

Większość z nich jest już dość dobrze zoptymalizowana.


Nie mogę ponownie uruchamiać usługi SQL, nawet jeśli zajmuje to tylko 2 sekundy, ponieważ mamy usługę alarmową, która pozwala ludziom zadzwonić i nagrać wiadomość, a następnie wybrana grupa zostanie wywołana i usłyszy nagraną wiadomość.

Z tego systemu korzystają setki ekip poszukiwawczych i ratowniczych, a jeśli usługa SQL uruchomi się ponownie podczas alarmu, zakończy działanie i osoba, która go wezwała, nie zostanie powiadomiona.


Szukałem wszędzie, ale nie znalazłem nic poza „Maskami koligacji”, których nie mogę zmienić.

Musi istnieć sposób na wyczyszczenie pamięci podręcznej procesora bez przerywania bieżących zapytań ... prawda?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
Levi Johansen
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Paul White 9

Odpowiedzi:

7

To długa szansa, ale możesz rzucić okiem na ustawienia wymuszonej parametryzacji. Jeśli widzisz dużą liczbę planów zapytań, gdy wydajność jest niska, twoje zapytania nie są buforowane w sposób, w jaki się ich spodziewasz, a zapytania zajmują dużo czasu, aby przejrzeć pamięć podręczną, aby sprawdzić, czy istnieje już plan użycia. Jeśli wyczyszczenie pamięci podręcznej rozwiązuje ten problem, warto rozważyć zmianę ustawienia wymuszonej parametryzacji. Możesz wyczyścić pamięć podręczną, używając:

DBCC FREEPROCCACHE

Możesz sprawdzić, jakie jest ustawienie wymuszonej parametryzacji, jeśli wyczyszczenie pamięci podręcznej działało:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Prawdopodobnie jest to wartość domyślna 0. Jeśli chcą, możesz to ustawić, wykonując:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Należy to zrobić najpierw w środowisku programistycznym i sprawdzić, czy wpłynie to negatywnie na bazę danych w inny sposób. Można to cofnąć za pomocą:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
Drew Leffelman
źródło
5
Zwróć uwagę, że zwolnienie pamięci podręcznej procedur może spowodować ogromny skok procesora - ponieważ wszystkie zapytania będą musiały ponownie skompilować swoje plany wykonania.
Aaron Bertrand
18

Powinowactwo nie „dostosowuje użycia procesora” (np. W twoim przypadku powoduje, że procesory wykonują mniej pracy), pozwala albo wyłączyć procesor (być może udostępnić go innej instancji na tym samym komputerze), albo ustawić procesor na pomoc tylko z I / O. Nawet jeśli miałeś wiele procesorów, nie byłbyś w stanie użyć tego pierwszego do pomocy w osiągnięciu celu, a nie możemy zgadywać na drugim, ponieważ nie wiemy, co powoduje tak wysokie użycie procesora. Może to być spowodowane bardzo słabym indeksowaniem, nadmiernymi kompilacjami, dużą ilością skalarnych UDF, przebijaniem We / Wy, kto wie? (A powodem, dla którego operacje wejścia / wyjścia mogą być przyczyną, jest to, że jeśli baza danych jest większa niż około 3 GB, będzie musiała stale wymieniać dane z pamięci puli buforów i z niej wyrzucać, a to odbije się na procesorze.)

Pamięć podręczna procesora to również królicza nora, której nie musisz schodzić. Wątpię, czy Twój procesor bije w 95% z powodu problemów z pamięcią podręczną procesora.

Aby pomóc zawęzić źródło obciążenia procesora i zakładając, że korzystasz z procedur przechowywanych, możesz rzucić okiem na to zapytanie diagnostyczne od Glenna Berry'ego ( tutaj ) - upewnij się, że uruchamiasz je w kontekście odpowiedniej bazy danych:

-- 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

Jeśli nie korzystasz z procedur przechowywanych, ten przykład od Johna Samsona może pomóc w wyodrębnieniu zapytań ad hoc ( pochodzących stąd ):

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);

Możesz także rzucić okiem na sp_WhoIsActive Adama Machanica , procedurę składowaną, która może szybko analizować wszystkie aktualnie uruchomione zapytania i umożliwiać sortowanie ich w dowolny sposób (np. W twoim przypadku @sort_order = '[CPU] DESC').

Pierwszą rzeczą, którą bym zrobił, zwłaszcza jeśli jest to naprawdę kluczowe dla zespołów poszukiwawczych i ratowniczych, jest zakup lepszego sprzętu. Powinieneś mieć więcej procesorów i więcej pamięci RAM do obsługi aplikacji. Absolutnie potrzebujesz też lepszej wysokiej dostępności (np. Klastrowania, kopii lustrzanej lub grup dostępności). Nie ma powodu, dla którego ponowne uruchomienie komputera fizycznego powinno całkowicie wyłączyć aplikację - mamy lepsze rozwiązania tego problemu. I wreszcie zakładam, że ten „serwer” ma tylko jeden dysk twardy. Oznacza to, że wszystkie operacje wejścia / wyjścia z systemu operacyjnego, z plików danych programu SQL Server, plików dziennika, tempdb itp. Przechodzą przez jeden kontroler i współużytkują operacje odczytu / zapisu na jednym dysku. Zdobądź więcej dysków. Zdobądź dyski SSD, jeśli / gdzie możesz. Użyj RAID i staraj się jak najbardziej rozpowszechnić We / Wy.

To powiedziawszy, rzucanie sprzętem na problem nie będzie jedyną częścią poprawki. Musisz dokładnie wyodrębnić, co powoduje nadmierne użycie procesora, a następnie zaatakować te problemy bez względu na sprzęt.

Zobacz także pytanie StackOverflow, aby uzyskać inne pomysły:

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

Aaron Bertrand
źródło
0

Poniższe sugestie są „strzałem w ciemność”, ponieważ nie widzę rzeczywistego kodu.

Po pierwsze, SP może otwierać kursory i pozostawiać je otwarte. Przeczytaj o Kursorach, szczególnie Zamknij i Zwolnij. Ktoś może się zamykać, ale nie zwalnia kursorów. Zachowanie mogło ulec zmianie w związku z aktualizacją, 2012 może traktować pozostałe kursory inaczej niż w 2008 R2.

Po drugie, mogą istnieć blokady tabeli, które nie zostaną usunięte. Znów jestem na odległość, więc nie mogę powiedzieć, ale sugerowałoby to, że ktoś utworzy globalną tabelę tymczasową po „rozpoczęciu transakcji” i albo nie zostanie wykonana „transakcja końcowa”, albo procedura przechowywana nie powiedzie się, pozostawiając zablokowaną tabela zajmująca miejsce w tempdb.

Czy przypadkiem korzystasz z WinLink? Coś w tym brzmi trochę znajomo.

Meredith Poor
źródło
-4

Powinieneś mieć mechanizm buforowania, taki jak memcached, aby poprawić wydajność


źródło
Ale to nie zmieniłoby użycia procesora na serwerze SQL, prawda? Po prostu sprawiłoby, że zapytania szłyby szybciej w witrynie, i mogą występować problemy, że coś się zmienia w tabeli, podczas gdy ktoś inny używa wyników memcache z tej samej tabeli, prawda?
Levi Johansen
@Levi, jeśli buforujesz wyniki zapytania gdzieś w środkowej warstwie, zapytania nie trafią do bazy danych (z wyjątkiem sytuacji, gdy musisz odświeżyć pamięć podręczną).
Aaron Bertrand
1
Jeśli procesor jest również wysoki, gdy nikogo nie ma na stronie, to oczywiście buforowanie rzeczy na poziomie sieci nie pomoże. Memcached to świetne narzędzie, ale nie zastępuje kompetentnej osoby, aby usiąść i dowiedzieć się, co robi serwer, kiedy podobno powinien nic nie robić.
TomTom