Skip to content

Под капотом SQL Server. Основы кэширования данных

Пересказ статьи Eduardo Pivaral. SQL Engine basics: Caching data



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

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



1 - данные запрашиваются скомпилированным запросом;
2 - движок проверяет, находятся ли нужные данные уже в памяти;
3 - если данных нет в памяти, они берутся из устройств хранения;
4 - данные помещаются в память.

По запросу ядро проверяет, находятся ли требуемые данные уже в памяти (или буферном пуле). Если данные там, они возвращаются. Если данных нет, то они запрашиваются с диска и помещаются в память, если буферный пул не заполнен.

Насколько долго данные сохраняются в буферном пуле зависит от различных аспектов: памяти, выделенной SQL Server, размера вашей базы данных, рабочей нагрузки, типа выполняемых запросов, OLTP в памяти и т.д.

Когда в буфере недостаточно места для выделения требуемой памяти, то происходит сброс данных, который состоит в том, что избыточные данные сохраняются в базе данных tempdb. Это обычно вызвано неточным выделением памяти. К счастью, в SQL Server 2019 реализована обратная связь по выделению памяти (Memory Grant feedback), которая помогает облегчить проблему.

Начиная с версии SQL Server 2014, вы также можете сконфигурировать расширения буферного пула, т.е. расширить память за счет более быстрых устройств хранения (обычно SDD или флеш-памяти). Об этом вы можете прочитать в документации Майкрософт.

Команды T-SQL


Теперь, когда вы имеете представление о том, как работает кэширование данных, давайте посмотрим на него в действии.

Для примеров мы будем использовать тестовую базу данных WideWorldImporters. Сначала мы выполним несколько запросов. Для нас не принципиально, что они делают; это может быть любой оператор SELECT:

DECLARE  @RawValue decimal(10,2) = 25000
SELECT SUM(UnitPrice * Quantity) as RawValue
FROM Sales.InvoiceLines
GROUP BY InvoiceID
HAVING SUM(UnitPrice * Quantity) > @RawValue;
SET @RawValue = RAND()*1500
SELECT InvoiceID, InvoiceLineID, UnitPrice,Quantity
FROM Sales.InvoiceLines
WHERE TaxAmount > @RawValue
OPTION(FAST 100);

Затем мы используем динамическое представление sys.dm_os_buffer_descriptors, чтобы проверить, какие данные находятся в памяти, сделав запрос более читабельным, например:

--ДЕТАЛИ ПО БАЗЕ ДАННЫХ:
SELECT
IIF(database_id = 32767,'ResourceDB',DB_NAME(database_id)) AS [Database],
file_id, --Этот файл находится на уровне базы данных,
-- он зависит от базы данных, на которой выполняется запрос
page_id,
page_level,
allocation_unit_id, -- можно соединить с sys.allocation_units (DMO уровня базы данных)
page_type,
row_count,
read_microsec
FROM sys.dm_os_buffer_descriptors BD
ORDER BY [Database], row_count DESC;

В зависимости от рабочей нагрузки мы получим что-то типа



Если вы предпочитаете что-то более компактное, можете выполнить запрос, группируя его по базе данных:

-- ЧТОБЫ ПОЛУЧИТЬ ИТОГИ ПО БАЗЕ ДАННЫХ:
SELECT
IIF(database_id = 32767,'ResourceDB',DB_NAME(database_id)) AS [Database],
COUNT(row_count) AS cached_pages
FROM sys.dm_os_buffer_descriptors
GROUP BY database_id
ORDER BY cached_pages DESC;

Вот результаты, сгруппированные по базе данных:



Чтобы очистить кэш от данных, выполните команду

DBCC DROPCLEANBUFFERS;

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

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

-- Проверяем, включено ли расширение буферного пула:
SELECT * FROM sys.dm_os_buffer_pool_extension_configuration;

Результат будет примерно таким (у меня не включено расширение буферного пула):

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.