Высокая загрузка ЦП на сервере SQL - медленные запросы [закрыто]

11

Наш MS SQL Server использует около 95% мощности процессора.

После перезапуска сервера (аппаратного обеспечения) или перезапуска службы SQL использование составляет 0% и медленно увеличивается в течение 1-3 дней. В зависимости от того, сколько это используется.

Когда оно превышает 80%, каждый запрос выполняется очень медленно.

Наш сайт имеет дело с большим количеством больших запросов, поэтому некоторые из них занимают 45-60 секунд. После перезапуска (загрузка ЦП менее 80%) на тот же запрос уходит 11-20 секунд.


Как я могу это исправить? Я читал в Интернете, что маски соответствия могут регулировать загрузку процессора, но настройки соответствия отключены. Я не могу их изменить. Это потому что у меня только 1 процессор?

Есть много хитростей, связанных с самими запросами, но наши сайты и сервисы довольно большие, и их просто слишком много, чтобы измениться.

Большинство из них уже довольно хорошо оптимизированы.


Я не могу продолжать перезапуск SQL-службы, даже если это занимает всего 2 секунды, потому что у нас есть служба сигнализации, которая позволяет людям звонить и записывать сообщение, после чего вызывается выбранная группа и слышит записанное сообщение.

Эта система используется сотнями команд поиска и спасения, и если служба SQL перезапускается во время тревоги, она прекращает работу, и лицо, вызвавшее ее, не будет уведомлено.


Я искал повсюду, но ничего не нашел, кроме материала о «Масках сходства», который я не могу изменить.

Должен быть способ очистки кэша ЦП без прерывания текущих запросов ... верно?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
Леви Йохансен
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Пол Уайт 9

Ответы:

7

Это долгий путь, но вы можете взглянуть на настройки принудительной параметризации. Если вы видите большое количество планов запросов, когда производительность плохая, ваши запросы не кэшируются так, как вы ожидаете, и запросам требуется много времени для сканирования в кэше, чтобы выяснить, есть ли план, который уже используется. Если очистка кэша решает эту проблему, вы можете захотеть изменить настройку принудительной параметризации. Вы можете очистить кеш, используя:

DBCC FREEPROCCACHE

Вы можете проверить, что такое параметр принудительной параметризации, если очистка кэша сработала:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Это, вероятно, установлено в 0, по умолчанию. Если они хотят, вы можете установить это на true, выполнив:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Это нужно сделать сначала в среде разработчиков и посмотреть, не влияет ли это отрицательно на базу данных другими способами. Это может быть восстановлено с помощью:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
Дрю Леффельман
источник
5
Обратите внимание, что освобождение кэша процедур может на самом деле вызвать огромный скачок в ЦП - поскольку все запросы теперь должны будут перекомпилировать свои планы выполнения.
Аарон Бертран
18

Сходство не «регулирует загрузку ЦП» (например, в вашем случае заставляет ЦП выполнять меньше работы), оно позволяет либо отключить ЦП (возможно, чтобы сделать его доступным для другого экземпляра на той же машине), либо установить ЦП на помощь только с вводом / выводом. Даже если бы у вас было несколько процессоров, вы не смогли бы использовать первый, чтобы помочь вам в достижении вашей цели, и мы не можем догадаться о втором, потому что мы не знаем, что приводит к такому высокому использованию вашего процессора. Это может быть из-за крайне плохой индексации, излишней компиляции, обилия скалярных UDF, перебоя ввода-вывода, кто знает? (И причина того, что ввод-вывод может быть причиной, заключается в том, что если ваша база данных больше 3 ГБ или около того, ей постоянно приходится обмениваться данными в и из памяти буферного пула, и это сказывается на ЦП.)

Кроме того, кэш-память процессора - это кроличья нора, которую вам не нужно закрывать. Я очень сомневаюсь, что ваш процессор работает на 95% из-за проблем с вашим кешем.

Чтобы сузить источник нагрузки на процессор и предположить, что вы используете хранимые процедуры, вы можете взглянуть на этот диагностический запрос от Гленна Берри ( источник отсюда ) - убедитесь, что вы запускаете его в контексте нужной базы данных:

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

Если вы не используете хранимые процедуры, то этот пример от Джона Самсона может помочь изолировать специальные запросы ( отсюда ):

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

Вы также можете взглянуть на sp_WhoIsActive Адама Мачаника , хранимую процедуру, которая может быстро проанализировать все выполняющиеся в данный момент запросы и позволить вам отсортировать их по своему усмотрению (например, в вашем случае @sort_order = '[CPU] DESC').

Первое, что я хотел бы сделать - особенно если это действительно важно для поисково-спасательных команд - это купить лучшее оборудование. У вас должно быть больше процессоров и больше оперативной памяти для обслуживания вашего приложения. Вам также абсолютно необходима лучшая высокая доступность (например, кластеризация, зеркалирование или группы доступности). Нет никаких причин, по которым перезагрузка физического компьютера должна переводить ваше приложение в автономный режим - у нас есть лучшие решения для этой проблемы. И, наконец, я предполагаю, что этот «сервер» имеет только один спиннид. Это означает, что все операции ввода-вывода - из операционной системы, из файлов данных SQL Server, файлов журналов, базы данных tempdb и т. Д. - проходят через один контроллер и совместно используют операции чтения / записи на одном диске. Получите больше дисков. Получить SSD, если / где вы можете. Используйте RAID и постарайтесь максимально расширить возможности ввода-вывода.

Это все сказало, бросая аппаратные средства в проблему не будет единственной частью исправления. Вы должны точно определить, что вызывает чрезмерную загрузку процессора, а затем атаковать эти проблемы, независимо от того, на каком оборудовании вы находитесь.

Также посмотрите этот вопрос StackOverflow для некоторых других идей:

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

Аарон Бертран
источник
0

Следующие предложения являются «выстрелом в темноте», потому что я не вижу реальный код.

Во-первых, SP может открывать курсоры и оставлять их открытыми. Читайте о курсорах, особенно Close и Deallocate. Кто-то может закрывать, но не освобождать курсоры. Поведение могло измениться из-за обновления, 2012 год может относиться к остальным курсорам иначе, чем в 2008 R2.

Во-вторых, это могут быть блокировки таблицы, которые не очищаются. Опять же, я нахожусь на расстоянии, поэтому не могу сказать, но можно предположить, что кто-то создает глобальную временную таблицу после «начальной транзакции», и либо не выполняется «конечная транзакция», либо хранимая процедура завершается неудачно, оставляя заблокированную таблица занимает место в базе данных tempdb.

Вы используете WinLink случайно? Что-то в этом звучит смутно знакомо.

Мередит Бедный
источник
-4

Для повышения производительности у вас должен быть механизм кэширования, такой как memcached.


источник
Но это не изменит загрузку ЦП на SQL-сервере, верно? Это только ускорит выполнение запросов на веб-сайте, и могут возникнуть проблемы, если кто-то изменится в таблице, а кто-то другой использует результаты memcached из той же таблицы, верно?
Леви Йохансен
@Levi, если вы кешируете результаты запроса где-то на среднем уровне, тогда запросы не попадают в базу данных (кроме случаев, когда вам нужно обновить кеш).
Аарон Бертран
1
Если процессор также высок, когда на сайте никого нет, то совершенно очевидно, что кеширование данных на веб-уровне не поможет. Memcached - отличный инструмент, но он не может заменить компетентного человека, который бы сел и узнал, что делает сервер, когда он, предположительно, ничего не должен делать.
TomTom