11.11.25

Потребление памяти запросами в SQL Server 2025

Автор: SQLYARD, SQL Query Memory Consumption in SQL Server 2025

Распределение памяти (memory grants) под запросы — один из ключевых и при этом часто недооцениваемых аспектов настройки производительности SQL Server. Если запрос просит больше памяти, чем ему нужно, падает параллелизм. Если слишком мало — происходят проливы в tempdb.

В SQL Server 2025 Microsoft улучшила обратную связь по распределению памяти запроса (query memory grant feedback) и оптимизацию планов выполнения, благодаря чему движок управляет памятью заметно эффективнее, чем в SQL Server 2022. В этой статье мы рассмотрим, как эти изменения влияют на производительность запросов, сравним уровни совместимости 160 и 170.

Почему важно, сколько памяти потребляет запрос

Каждый запрос в SQL Server запрашивает распределение памяти — зарезервированный объём для операций сортировки и хеширования. Когда один запрос потребляет слишком много, остальные ждут на семафоре ресурсов, что блокирует параллелизм.

Механизм обратной связи по распределению памяти (memory grant feedback, появился в 2017) корректирует распределение, опираясь на предыдущие исполнения. В SQL Server 2025 этот цикл обратной связи стал быстрее и точнее.

Итог: более стабильное потребление памяти и меньше впустую потраченной ОЗУ на каждый запрос.

Подготовка тестового окружения

Для демонстрации используем:

  • SQL Server 2025 RC0 или RC1
  • Тестовую базу StackOverflow (свободно доступна на StackOverflow.com)
  • Запрос, находящий топ‑100 пользователей с наивысшей репутацией, возвращающий только лучшего пользователя по каждой локации.

Шаг 1 — тест на уровне совместимости 160 (SQL Server 2022)

Сначала переключите базу на уровень совместимости 160 и выполните следующий запрос.

USE master;
GO
ALTER DATABASE StackOverflow SET COMPATIBILITY_LEVEL = 160;
GO
USE StackOverflow;
GO
;WITH Tbl AS
(
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY u.Location ORDER BY u.Reputation DESC) AS rn,
        u.Id, u.Age, u.CreationDate, u.DisplayName, u.DownVotes,
        u.EmailHash, u.LastAccessDate, u.Location, u.Reputation,
        u.UpVotes, u.Views, u.WebsiteUrl, u.AccountId
    FROM dbo.Users u
    WHERE u.Location IS NOT NULL AND Location <> ''
)
SELECT TOP 100 
    t.Id, t.Age, t.CreationDate, t.DisplayName, t.Reputation, t.Location
FROM Tbl t
WHERE t.rn = 1
ORDER BY t.Reputation DESC;
GO

Чтобы зафиксировать детали по памяти, включите Include Actual Execution Plan в SSMS (Ctrl + M).

Вы увидите, что оптимизатор выполняет сканирование кластерного индекса и использует операторы Sort и Window Aggregate. Это необходимо, чтобы вычислить функцию ROW_NUMBER() и упорядочить результат по репутации.

Наблюдение за распределением памяти

Щёлкните правой кнопкой по оператору SELECT в плане выполнения и откройте Properties.

Вы заметите:

  • Granted Memory: ~2700 MB
  • IsMemoryGrantFeedbackAdjusted: No (First Execution)

Выполните тот же запрос ещё три раза:

GO 3

Теперь распределение памяти сокращается примерно до 946 MB, а IsMemoryGrantFeedbackAdjusted меняется на Yes: Stable.

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

Шаг 2 — тест на уровне совместимости 170 (SQL Server 2025)

Включим возможности SQL Server 2025.

ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 170;
GO

Выполните тот же запрос снова:

;WITH Tbl AS  
(  
SELECT  
ROW_NUMBER() OVER (PARTITION BY u.Location ORDER BY u.Reputation DESC) AS rn,  
u.Id, u.Age, u.CreationDate, u.DisplayName, u.Reputation, u.Location  
FROM dbo.Users u  
WHERE u.Location IS NOT NULL AND Location <> ”  
)  
SELECT TOP 100  
t.Id, t.DisplayName, t.Reputation, t.Location  
FROM Tbl t  
WHERE t.rn = 1  
ORDER BY t.Reputation DESC;  
GO

Сравнение планов выполнения

План запроса теперь немного меняется. Оптимизатор фильтрует результаты до финальной сортировки, снижая число промежуточных строк и потребность в памяти.

Распределение памяти: ~1427 MB
IsMemoryGrantFeedbackAdjusted: No (First Execution)

Запустите запрос ещё три раза:

GO 3

Распределение памяти стабилизируется примерно на уровне 467 MB, то есть вдвое меньше, чем при уровне совместимости SQL Server 2022.

Мониторинг семафоров ресурсов

SELECT * 
FROM sys.dm_exec_query_memory_grants
WHERE grant_time IS NOT NULL
ORDER BY requested_memory_kb DESC;

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

Анализ в Query Store

Если Query Store включён, можно сравнить показатель Memory Grant (KB) во времени посредством запроса:

SELECT 
    qs.query_id,
    qs.avg_memory_grant_kb,
    qs.last_execution_time
FROM sys.query_store_runtime_stats qs
ORDER BY qs.avg_memory_grant_kb DESC;

Итоги

В этом тесте SQL Server 2025 на уровне совместимости 170 потребил примерно на 50% меньше памяти для той же нагрузки по сравнению с уровнем 160 (2022).

Основные выводы:

  • Обратная связь по распределению памяти стала быстрее и точнее.
  • Оптимизатор запросов лучше сокращает число строк до выполнения сортировок.
  • Улучшения в эвристиках планов выполнения сокращают избыточное распределение памяти.

Хотя не всякая нагрузка покажет такие же цифры, тренд очевиден: SQL Server 2025 обеспечивает более экономное потребление памяти на запрос, повышая параллелизм и устойчивость на загруженных системах.

Давление на память остаётся одной из самых скрытых причин деградации производительности. SQL Server 2025 продолжает курс Microsoft на самонастраивающееся поведение — от интеллектуальной обработки запросов до адаптивных контуров обратной связи.

Если вы переходите с SQL Server 2019 или 2022, включение уровня совместимости 170 — простой способ сразу получить эти преимущества.

Всегда контролируйте DMV, Query Store и планы выполнения, чтобы подтвердить выигрыш в вашей среде, и обязательно сравнивайте показатели до и после обновления.

Комментариев нет:

Отправить комментарий