SQL Server сильно грузит процессор. Проблемы CPU у процесса SQLServer. Оптимизация запросов SQL по CPU

Время чтения - 15 мин.Дата публикации 26.04.2020 (обновлено 13.05.2026)

Диагностика и устранение высокой загрузки CPU в SQL Server

Первичная диагностика: откройте Диспетчер задач, перейдите на вкладку «Подробности», найдите процесс sqlservr.exe и проверьте значение в колонке «ЦП». Если этот показатель стабильно высокий, это указывает на проблему с утечкой CPU.

В этом руководстве собраны проверенные методы для выявления и устранения причин высокой загрузки процессора SQL Server.

1. Анализ счетчиков PerfMon

Определите, вызвана ли проблема системными (Kernel) или пользовательскими (User) запросами. В оснастке PerfMon отслеживайте следующие счетчики:

  • Processor: % Privileged Time – процент времени, затраченного процессором на выполнение команд ядра Windows (например, активность ОС). Значение более 30% может указывать на проблемы, связанные с администрированием Windows.
  • Process (sqlservr): % Privileged Time – суммарное процессорное время на всех ядрах для всех потоков процесса SQL Server (ядро SQL).
  • Processor: % User Time – процент времени, затраченного на выполнение пользовательских процессов, включая запросы SQL Server и связанные с ними операции ввода-вывода.

Если значение (% Privileged Time / Количество логических процессоров) превышает 30%, проблема, скорее всего, в системных настройках, например, в работе антивируса.

Для поиска конкретных проблемных spID, загружающих процессор, используйте эту инструкцию.

2. Поиск проблемных процессов

Выполните запрос для поиска системных процессов, потребляющих ресурсы:

SELECT * FROM sys.sysprocesses
WHERE cmd like 'LAZY WRITER' or cmd like '%Ghost%' or cmd like 'RESOURCE MONITOR'

Альтернативный вариант для поиска по потреблению CPU:

SELECT top 20 spid, kpid, dbid, cpu, memusage FROM sysprocesses
order by cpu desc

Обратите внимание: spID от 1 до 50 — системные. Для работы с пользовательскими процессами используйте фильтр spID > 50. Вы можете завершить проблемный процесс командой KILL spID и сразу оценить влияние на загрузку CPU.

Для получения информации о текущем состоянии всех процессов используйте хранимые процедуры: sp_who, sp_who1, sp_who2, sp_who3.

Чтобы найти текст запроса по spID:

DECLARE @sqltext VARBINARY(128)
SELECT @sqltext = sql_handle
FROM sys.sysprocesses
WHERE spid = 78
SELECT TEXT
FROM sys.dm_exec_sql_text(@sqltext)
GO

Также можно просмотреть последний выполняющийся запрос для spID:

DBCC INPUTBUFFER(60)
GO
SELECT @@SPID  -- получить SPID текущего процесса
GO

3. Выявление проблем через специализированные запросы

Используйте следующие запросы для поиска проблемных мест по CPU.

Запрос 1: Детальная информация о выполняющихся запросах с сортировкой по времени CPU.

SELECT GETDATE() AS "RunTime", st.text AS batch, SUBSTRING(st.text,statement_start_offset / 2+1
,((CASE WHEN a.statement_end_offset = -1
THEN (LEN(CONVERT(nvarchar(max),st.text)) * 2)
ELSE a.statement_end_offset END)  - a.statement_start_offset) / 2+1)  AS current_statement
, qp.query_plan, a.*
FROM sys.dm_exec_requests a CROSS APPLY sys.dm_exec_sql_text(a.sql_handle) AS st
CROSS APPLY sys.dm_exec_query_plan(a.plan_handle) AS qp
ORDER BY CPU_time DESC

Запрос 2: Группировка процессов по выполняемому коду для выявления наиболее ресурсоемких групп.

/*
Disclaimer: I am not sure for the origin of this script/query.
This query is used in our team to identify and resolve high CPU issue

*/
--define the temptables that will hold intermediary results
IF OBJECT_ID('tempdb..#dbcc') IS NOT NULL
    DROP TABLE #dbcc

create table #dbcc(c1 varchar(15), c2 int, c3 varchar(255),spid int default 0)

IF OBJECT_ID('tempdb..#cpugroups') IS NOT NULL
    DROP TABLE #cpugroups

create table #cpugroups (sql_handle binary(20), sql_text nvarchar(50),total_cpu bigint,total_io bigint,total_sessions int, total_threads int)


--take the SPID groups that are running same code (NOT statement)
insert into #cpugroups
select top 10 sql_handle,substring((select text from fn_get_sql(sql_handle)),1,50), SUM(CPU) TotalCPUForGroup, SUM(physical_io) TotalIOForGroup, COUNT(distinct spid) TotalNoOfSessions,COUNT(*) TotalNoOfThreads
from master..sysprocesses (nolock)
where spid>50 and status<>'sleeping'
and sql_handle<>0x0 and spid<>@@spid
group by sql_handle
order by TotalCPUForGroup desc


declare @sql nvarchar(max)
declare @t table (spid int)

INSERT INTO @t
SELECT DISTINCT spid FROM master..sysprocesses WHERE spid>50 and sql_handle in (select sql_handle from #cpugroups)


declare @spid int


WHILE EXISTS(select * from @t)
BEGIN
  select top 1 @spid=spid from @t
  set @sql='dbcc inputbuffer('+LTRIM(STR(@spid))+')'

  --try to retrieve the original command for all SPIDs
  BEGIN TRY
    INSERT INTO #dbcc(c1, c2, c3)
    EXEC (@sql)

    update #dbcc
    set spid=@spid
    where spid=0

  END TRY
  BEGIN CATCH
  END CATCH


  delete from @t where spid=@spid

END


select * from #cpugroups
select c3 [sql_text], count(*) NoOfSessionsRunning from #dbcc group by c3 order by 2 desc
select * from #dbcc

Для очистки плана конкретного запроса из кэша используйте его plan_handle:

DBCC FREEPROCCACHE (plan_handle_id_goes_here)

Запрос 3: Поиск запросов с наибольшим временем CPU (с планом выполнения).

SELECT
	r.session_id
	,st.TEXT AS batch_text
	,SUBSTRING(st.TEXT, statement_start_offset / 2 + 1, (
			(
				CASE
					WHEN r.statement_end_offset = - 1
						THEN (LEN(CONVERT(NVARCHAR(max), st.TEXT)) * 2)
					ELSE r.statement_end_offset
					END
				) - r.statement_start_offset
			) / 2 + 1) AS statement_text
	,qp.query_plan AS 'XML Plan'
	,r.*
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
CROSS APPLY sys.dm_exec_query_plan(r.plan_handle) AS qp
ORDER BY cpu_time DESC

Запрос 4: Комплексный анализ сессий с блокировками и ожиданиями.

SELECT s.session_id,
r.status,
r.blocking_session_id 'Blk by',
r.wait_type,
wait_resource,
r.wait_time / (1000 * 60) 'Wait M',
r.cpu_time,
r.logical_reads,
r.reads,
r.writes,
r.total_elapsed_time / (1000 * 60) 'Elaps M',
Substring(st.TEXT,(r.statement_start_offset / 2) + 1,
((CASE r.statement_end_offset
WHEN -1
THEN Datalength(st.TEXT)
ELSE r.statement_end_offset
END - r.statement_start_offset) / 2) + 1) AS statement_text,
Coalesce(Quotename(Db_name(st.dbid)) + N'.' + Quotename(Object_schema_name(st.objectid, st.dbid)) + N'.' +
Quotename(Object_name(st.objectid, st.dbid)), '') AS command_text,
r.command,
s.login_name,
s.host_name,
s.program_name,
s.last_request_end_time,
s.login_time,
r.open_transaction_count
FROM sys.dm_exec_sessions AS s JOIN sys.dm_exec_requests AS r
ON r.session_id = s.session_id CROSS APPLY sys.Dm_exec_sql_text(r.sql_handle) AS st
WHERE r.session_id != @@SPID
ORDER BY r.cpu_time desc

Также воспользуйтесь встроенным отчетом: кликните правой кнопкой мыши на сервере в SSMS → Reports → Standard Reports → «Top CPU queries».

4. Анализ найденных проблемных запросов

Для каждого найденного запроса изучите его план выполнения (execution plan) и определите операции с наибольшей стоимостью (cost).

Рекомендации по оптимизации:

  • Проверьте наличие и актуальность индексов для таблиц, участвующих в проблемных запросах.
  • Максимально сужайте выборку данных на ранних этапах выполнения запроса (в секции WHERE). Избегайте сканирования больших таблиц без эффективной фильтрации.
  • Проверьте наличие неявных или затратных преобразований типов данных.
  • Если используются функции, убедитесь, что они минимизируют количество операций внутри себя.
  • Рассмотрите установку актуальных обновлений для SQL Server, например, исправление для высокой загрузки CPU в SQL Server 2016 и 2017.
    select * from sys. dm_os_spinlock_stats -- проверьте, нет ли аномально высоких значений у счетчиков SECURITY_CACHE и CMED_HASH_SET. Если есть — установите обновления.
  • Используйте sys.dm_exec_query_plan для просмотра планов тяжелых запросов.
  • Для получения текста запроса по sql_handle или plan_handle используйте sys.dm_exec_sql_text.

Полезные источники по теме утечек CPU

Альтернативный чек-лист для диагностики проблем CPU

Что проверить в первую очередь:

  • Конфигурация аппаратного обеспечения сервера.
  • Состояние дисковой подсистемы (скорость, задержки, свободное место).
  • Наличие и настройки антивируса (добавьте папки SQL Server и файлы БД в исключения).
  • Активность базы данных: какие операции выполняются и с какой частотой.
  • Выполнение проверки целостности БД (DBCC CHECKDB).
  • Перестройка индексов и обновление статистики.
  • Операции сжатия (shrink) данных.

Общие системные рекомендации

Статья о производительности SQL Server после миграции

  • Электропитание: Установите схему «Высокая производительность».
  • Дисковая подсистема: Настройте кэширование записи на диск (Write-Back Cache).
  • Параллелизм: Проверьте и настройте параметры cost threshold for parallelism и max degree of parallelism.
  • Hyper-Threading: Оцените влияние и при необходимости скорректируйте настройки.

Мониторинг через SSMS: Стандартные отчеты

В SQL Server Management Studio доступен набор стандартных отчетов для быстрой диагностики. Доступ: «Обозреватель объектов» → Правый клик по базе данных → «Отчеты» → «Стандартный отчет».

Наиболее полезные отчеты для диагностики CPU:

  • Все транзакции
  • Все блокирующие транзакции
  • Самые продолжительные транзакции
  • Транзакции, блокирующие наибольшее количество транзакций
  • Транзакции с наибольшим количеством блокировок
  • Статистика блокировки ресурсов по объектам
  • Статистика выполнения объектов
  • Статистика использования индекса
  • Физическая статистика индекса

Мониторинг через Activity Monitor (Монитор активности)

Откройте через CTRL+ALT+A или через стандартную панель инструментов SSMS. Предоставляет обзорную информацию по процессам, ожиданиям, вводу-выводу и последним ресурсоемким запросам, аналогично Диспетчеру задач Windows.

Мониторинг через Performance Dashboard Reports

Пакет отчетов SQL Server Performance Dashboard Reports для Reporting Services. Скачать и ознакомиться. Отчеты предназначены для использования с функцией Custom Reports в SSMS.

Платные решения для мониторинга

Обзор платных решений

  • Idera — SQL Diagnostic Manager
  • Red-Gate — SQL Monitor
  • ApexSQL — ApexSQL Monitor
  • Quest — Spotlight on SQL Server Enterprise
  • SentryOne — SQL Sentry

Также возможен мониторинг SQL Server через Zabbix.

Полезные системные скрипты и процедуры

sp_who и sp_who2

Для поиска блокирующих и ожидающих запросов.

1. sys.dm_exec_query_stats (наибольшее время CPU)

Запрос для определения запросов, потребляющих больше всего процессорного времени.

2. sys.dm_exec_query_stats (утилизация CPU, IO, памяти)

Пример результата:

row_num

DatabaseName

CPU_Time(Ms)

CPUPercent

1

master

6355553

88.11

2

АutoParts_shop_v2

357018

4.95

3

testDB_1

255776

3.55

4

tempdb

244863

3.39

5

msdb

142

0

3. sys.dm_exec_query_stats (тяжелые запросы)

Скрипт на основе представления sys.dm_exec_query_stats.

4. sys.dm_tran_locks (заблокированные запросы)

Быстрый способ найти заблокированные запросы. Для разблокировки используйте KILL blocking_session_id.

5. Нагрузка на процессор

Запрос для определения, какой процессор и чем загружен.

6. Информация о пользователях и подключениях

Основан на представлениях: sys.dm_exec_connections, master.sys.sysprocesses, sys.dm_exec_sessions.

Скрипт: sp_WhoIsActive

Комплексная хранимая процедура для мониторинга текущей активности сервера. Источник: whoisactive.com. Показывает, кто и что вызывает нагрузку в данный момент. Подходит для сбора и последующего анализа данных. Использует 15 DMV.

Пример вызова с ключевыми параметрами:

                               @show_sleeping_spids = 2,  -- Показать спящие сессии

                               @show_system_spids = 1, -- Показать системные сессии

                               @show_own_spid = 1  --  Показать вашу собственную сессию

                               , @get_full_inner_text = 1 -- видеть всю активность,

                               , @get_outer_command = 1 -- что вызвало этот [sql_text]

                               , @get_task_info = 1 -- Вывести в столбец [wait_info] не только самое важное ожидание, но и все остальные:

                               , @get_transaction_info = 1 --9. Можно так же убрать агрегацию транзакций одной сессии и вывести их по отдельности:

                               , @get_additional_info = 1 --10. Вывести более детальную информацию. Будет добавлен столбец [additional_info] с информацией в формате XML

                               -- , @find_block_leaders = 1 -- количество заблокированных процессов каждой сессией:

                               , @sort_order = '[CPU] DESC' -- сортировку вывода

Скрипт: sp_Blitz

Внешняя процедура для быстрой проверки состояния сервера. Устанавливается в любую БД. Источники: Brent Ozar: Ask Brent, Brent Ozar: First Aid.

Как работает:

  1. Установите процедуру.
  2. Запустите в любое удобное время (выполняется 5-15 секунд, минимально влияя на других пользователей).

Варианты использования:

--dbo.sp_Blitz -- общие параметры
--sp_BlitzFirst - "Why is my SQL Server slow right now?"
--sp_BlitzCache - "What are the most resource-intensive queries on this server?"
--sp_BlitzIndex - "How could I tune indexes to make this database faster?"
--sp_BlitzQueryStore - "How has this query performed over time?" (для SQL Server 2016+)
--sp_BlitzWho --"Who's running what queries right now?"

SQL Profiler и Extended Events

SQL Profiler — быстрый способ просмотра выполняемых запросов. Несмотря на то, что считается устаревшим, остается популярным инструментом. Является графической надстройкой для SQL Trace (также устаревшего). SQL Trace находится в режиме поддержки и может быть удален в будущем.

Extended Events — современная замена SQL Profiler. В SSMS находятся в разделе «Управление» → «Расширенные события» → «Сеансы».

Насколько полезной была статья?

Что еще посмотреть по SQL Server

Определение какая база данных создает нагрузку на CPU

Оптимизация SQL - медленная конвертация таблицы в строку

Медленный sql. Как найти, что вызывает замедление в хранимой процедуре MS SQL

Анализ статистики по индексам в базе данных SQL Server

Способы оптимизации SQL запросов с примерами

Как найти медленные проблемные запросы SQL Server. Оптимизация быстродействия SQL Server

SQL Server. Работа с индексами через запросы SQL

Где ставить индексы SQL Server

Оптимизация SQL запросов, план запроса в SQL Server

Решение проблем с большим кешем запросов SQL Server

Инструмент для анализа производительности запросов SQL Server Query Store

SQL Server Как найти запросы с проблемами (warning) в плане выполнения запроса (SQL Plan)

Дополнительный заработок для разработчиков на T-SQL

Прямая работа с заказчиками как ИП или самозанятый. Нужно знать только SQL и HTML.
Falcon Space - платформа для создания сайтов с личными кабинетами
В 2-3 раза экономнее и быстрее, чем заказная разработка
Более гибкая, чем коробочные решения и облачные сервисы
Используйте готовые решения и изменяйте под свои потребности
Запрос расчета стоимости веб-проекта на базе Falcon Space
Если видео Youtube плохо грузится, то попробуйте найти видео в ВК видео на канале Falcon Space
Сайт использует Cookie, Яндекс Метрику. Используя сайт, вы соглашаетесь с правилами сайта. См. Правила конфиденциальности и Правила использования сайта OK