Заполнение или прогрев кеша в SQL Server - PullRequest
9 голосов
/ 04 февраля 2010

Когда я тестирую запрос, я обычно опускаю следующие строки перед тем, что я тестирую, чтобы убедиться, что я начинаю с одной и той же базовой линии каждый раз, когда я запускаю запрос.

CHECKPOINT
GO
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
EXEC sp_MyProc 12345

На сохраненном процессе, который я запускал сегодня, я заметил, что когда я запускал его с этими строками, это занимало примерно 18 минут каждый раз.Когда я оставил эти строки неактивными, потребовалось только 3. Увидев существенное различие, вызванное наличием очищенного кэша по сравнению с заполненным кэшем, я решил добавить следующее, чтобы посмотреть, можно ли вручную заполнить кэш перед запуском моего процесса и посмотреть, что это сделало сспектакль.

CHECKPOINT
GO
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
SELECT top 1 '1' from Table1
EXEC sp_MyProc 12345

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

  • Делает ли это для повышения производительности ваших запросов, не слышали?
  • Правильно ли я даже предположил, что улучшение во времени, которое я увидел, было результатом «загрунтованного» кэша?

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

ОБНОВЛЕНИЕ: Что ж, мне стыдно сказать, что я пытался воспроизвести это поведение сегодня, но не смог.Я разговаривал с некоторыми людьми на моей работе, и похоже, что некоторые вещи, которые они делали на БД вчера, могли заставить его выглядеть так, как будто мой выбор перед процедурой улучшал производительность, хотя на самом деле это не так.Мне все еще было бы интересно услышать, если кто-нибудь знает, возможно ли "заправить" кеш через

Ответы [ 3 ]

3 голосов
/ 04 февраля 2010

Предоставление «ответа», чтобы попытаться решить эту проблему, поскольку это то, что меня особенно интересует.

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

SELECT count(*) AS cached_pages_count, obj.name, index_id, i.name AS IndexName
FROM sys.dm_os_buffer_descriptors AS bd 
    INNER JOIN 
    (
        SELECT object_id, object_name(object_id) AS name 
            ,index_id ,allocation_unit_id
        FROM sys.allocation_units AS au
            INNER JOIN sys.partitions AS p 
                ON au.container_id = p.hobt_id 
                    AND (au.type = 1 OR au.type = 3)
        UNION ALL
        SELECT object_id, object_name(object_id) AS name   
            ,index_id, allocation_unit_id
        FROM sys.allocation_units AS au
            INNER JOIN sys.partitions AS p 
                ON au.container_id = p.partition_id 
                    AND au.type = 2
    ) AS obj 
        ON bd.allocation_unit_id = obj.allocation_unit_id
    LEFT JOIN sysindexes i ON obj.object_id = i.id AND obj.index_id = i.indid
WHERE database_id = db_id()
GROUP BY obj.name, index_id, i.name
ORDER BY cached_pages_count DESC;

Если вы попытаетесь выполнить следующие шаги, вы сможете увидеть, что происходит с кэшированием. Сделайте это в своей базе данных (в отличие, например, от master):

1) контрольная точка + очистка кеша
2) запустите приведенный выше запрос, и вы, вероятно, получите 1 возвращенную запись (для sysobjvalues), но ничего для Table1
3) теперь запустите оператор SELECT TOP 1 '1' FROM MyTable
4) повторно запустите приведенный выше запрос и посмотрите, что теперь появляется в результатах - вы, вероятно, увидите записи для MyTable, показывающие кэшированные страницы - запишите это число

Это должно дать вам представление об уровне кэширования данных, которое происходит для этого начального SELECT. Если вы повторите процесс до конца, но вместо оператора SELECT TOP выполните sproc, а затем посмотрите, сколько окажется в кэше при его запуске - возможно, сравнение этих результатов покажет относительный объем кэширования, который выполняется ВЫБЕРИТЕ ТОП 1 по сравнению с вызовом sproc - и эта относительная величина может указывать на улучшение производительности.

Это очень много "продуманных вслух" вещей. Я бы не подумал, что ТОП-1 действительно значительно заполнил бы кэш для вызова sproc, но именно поэтому меня интересует этот вопрос!

Сначала я бы подумал, что это связано с другими факторами (например, нагрузка на сервер / диск). Вы можете переключаться между двумя сценариями для 3 или 4 итераций, одна за другой, чтобы дважды проверить, действительно ли подход SELECT TOP действительно лучше (помочь минимизировать риск того, что он будет одноразовым)

Надеюсь, это поможет / заставит шарик катиться.

Обновление:
Теперь вы знаете, что это не SELECT TOP, который заполняет кеш, хороший способ заполнить кеш, как сказал AdrianBanks. По крайней мере, теперь вы можете объяснить, что было неожиданным / сбивающим с толку разницу в производительности! Сохраните приведенный выше скрипт в своей библиотеке, это полезно для проверки состояния кэша.

2 голосов
/ 05 февраля 2010

Ваше обновление вашего вопроса соответствует тому, что я ожидаю.Я не понимаю, как выполнение запроса SELECT 1... может принести реальную производительность для последующего запроса.

Насколько я понимаю, SQL Server загружает страницы данных (содержащие данные таблицы или данные индекса) в памятькак это нужно им при выполнении запросов.Они хранятся в памяти до тех пор, пока они не будут явно очищены (с использованием DBCC DROPCLEANBUFFERS - т. Е. Удалены все буферы (кэшированные страницы) в памяти, которые не были изменены с момента загрузки), или существует нехватка памяти (либо недостаточно свободной памяти на машине, либомаксимальный объем памяти, установленный на SQL Server).Из-за этого поведения может быть полезно прогреть базу данных SQL Server для использования.При последующем выполнении запроса данные, необходимые для сбора результатов запроса, могут уже находиться в памяти.Если это так, то запрос будет выполняться быстрее, поскольку он потребует меньшего количества операций ввода-вывода.

Проблема, однако, заключается в том, чтобы знать, что предварительно кэшировать и, следовательно, какие запросы выполнять.Вы можете запустить трассировку SQL для типичной активности, а затем воспроизвести ее для предварительного кэширования данных, которые часто используются.Однако, не позволяя SQL Server занимать большой объем выделенной памяти, вам всегда придется считывать некоторые данные с диска (если у вас нет небольшой базы данных).Поскольку вы никогда не узнаете, что кэшируется, а что нет, полагаться на такое поведение для производительности кажется неправильным.

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

0 голосов
/ 18 июня 2016

Один из способов заполнения кеша SQL Server для полных табличных данных (или их подмножеств) - запустить: SELECT SUM(CAST(BINARY_CHECKSUM(*) AS BIGINT)) FROM my_table

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

Настройте столбцы и добавьте операторы предложения WHERE для кэширования индексов или подмножеств таблицы по желанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...