Отключает / присоединяет или отключает / отключает очистку буферного кэша для конкретной базы данных?

8

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

Я использую AdventureWorks2012 в этой версии SQL Server:

ВЫБЕРИТЕ @@ VERSION;
Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
Developer Edition (64-разрядная версия) в Windows NT 6.1 (сборка 7601: пакет обновления 1)

Загрузив базу данных, я запускаю следующий запрос:

Во-первых, запустите сценарий откорма Jonathan K AW, найденный здесь:

AW получить жир

---------------------------
- Шаг 1: Булл-хаус?
---------------------------
ИСПОЛЬЗОВАНИЕ [AdventureWorks2012];
ИДТИ

ВЫБРАТЬ
     OBJECT_NAME (p.object_id) AS [ObjectName]
   , p.object_id
   , p.index_id
   , COUNT (*) / 128 AS [размер буфера (МБ)]
   , COUNT (*) AS [buffer_count]
ОТ
     sys.allocation_units AS a
     ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.dm_os_buffer_descriptors AS b
           ON a.allocation_unit_id = b.allocation_unit_id
     ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.partitions AS p
           ON a.container_id = p.hobt_id
ГДЕ
     b.database_id = DB_ID ()
     AND p.object_id> 100
ГРУППА ПО
     p.object_id
   , p.index_id
СОРТИРОВАТЬ ПО
     buffer_count DESC;

Результат показан здесь: введите описание изображения здесь

Отсоедините и снова присоедините базу данных, а затем повторно запустите запрос.

---------------------------
- Шаг 2: отсоединить / прикрепить
---------------------------
- отсоединить
ИСПОЛЬЗОВАТЬ [мастер]
ИДТИ
EXEC master.dbo.sp_detach_db @dbname = N'AdventureWorks2012 '
ИДТИ

-- Прикреплять
ИСПОЛЬЗОВАТЬ [мастер];
ИДТИ

СОЗДАТЬ БАЗУ ДАННЫХ [AdventureWorks2012] ВКЛ 
( 
    FILENAME = N'C: \ sql server \ files \ AdventureWorks2012_Data.mdf ' 
)
    ,
( 
    FILENAME = N'C: \ sql server \ files \ AdventureWorks2012_Log.ldf ' 
)
 ДЛЯ ПРИЛОЖЕНИЯ;
ИДТИ

Что сейчас в пуле?

---------------------------
- Шаг 3: Bpool Stuff?
---------------------------
ИСПОЛЬЗОВАНИЕ [AdventureWorks2012];
ИДТИ

ВЫБРАТЬ
     OBJECT_NAME (p.object_id) AS [ObjectName]
   , p.object_id
   , p.index_id
   , COUNT (*) / 128 AS [размер буфера (МБ)]
   , COUNT (*) AS [buffer_count]
ОТ
     sys.allocation_units AS a
     ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.dm_os_buffer_descriptors AS b
           ON a.allocation_unit_id = b.allocation_unit_id
     ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.partitions AS p
           ON a.container_id = p.hobt_id
ГДЕ
     b.database_id = DB_ID ()
     AND p.object_id> 100
ГРУППА ПО
     p.object_id
   , p.index_id
СОРТИРОВАТЬ ПО
     buffer_count DESC;

И результат: введите описание изображения здесь

Все ли чтения логичны на этом этапе?

--------------------------------
- Шаг 4: только логическое чтение?
--------------------------------
ИСПОЛЬЗОВАНИЕ [AdventureWorks2012];
ИДТИ

ВКЛЮЧИТЬ СТАТИСТИКУ IO ON;   
    SELECT * FROM DatabaseLog;
    ИДТИ
ВЫКЛЮЧИТЬ СТАТИСТИКУ IO OFF;  

/ *
(Затронуто 1597 строк)
Таблица «DatabaseLog». Сканирование 1, логическое чтение 782, физическое чтение 0, чтение с опережением 768, логическое чтение с 94, физическое чтение с 4, предварительное чтение с чтения 24.
* /  

И мы видим, что буферный пул не был полностью удален отсоединением / присоединением. Похоже, мой друг ошибся. Кто-нибудь не согласен или есть лучший аргумент?

Другой вариант - отключить и затем подключить базу данных. Давайте попробуем это.

--------------------------------
- Шаг 5: Оффлайн / Онлайн?
--------------------------------
ALTER DATABASE [AdventureWorks2012] SET OFFLINE;
ИДТИ
ALTER DATABASE [AdventureWorks2012] SET ONLINE;
ИДТИ

---------------------------
- Шаг 6: Bpool Stuff?
---------------------------
ИСПОЛЬЗОВАНИЕ [AdventureWorks2012];
ИДТИ

ВЫБРАТЬ
     OBJECT_NAME (p.object_id) AS [ObjectName]
   , p.object_id
   , p.index_id
   , COUNT (*) / 128 AS [размер буфера (МБ)]
   , COUNT (*) AS [buffer_count]
ОТ
     sys.allocation_units AS a
     ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.dm_os_buffer_descriptors AS b
           ON a.allocation_unit_id = b.allocation_unit_id
     ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.partitions AS p
           ON a.container_id = p.hobt_id
ГДЕ
     b.database_id = DB_ID ()
     AND p.object_id> 100
ГРУППА ПО
     p.object_id
   , p.index_id
СОРТИРОВАТЬ ПО
     buffer_count DESC;

Похоже, что работа в автономном / онлайн режиме работала намного лучше.

введите описание изображения здесь

ooutwire
источник

Ответы:

9

Сначала я думал, что вы что-то здесь делаете. Рабочее предположение было в том же духе, что, возможно, буферный пул не был немедленно очищен, так как для этого требуется «некоторая работа» и зачем беспокоиться, пока не потребуется память. Но...

Ваш тест ошибочен.

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

И мы видим, что буферный пул не был полностью удален отсоединением / присоединением. Похоже, мой друг ошибся. Кто-нибудь не согласен или есть лучший аргумент?

Да. Вы интерпретируете physical reads 0как означающее, что не было никаких физических чтений

Таблица «DatabaseLog». Сканирование 1, логическое чтение 782, физическое чтение 0, чтение с опережением 768 , логическое чтение - 94, физическое чтение - 4, чтение с опережением - 24.

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

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

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

Относительно того, почему онлайн / офлайн приводит к другому профилю буферного пула, требуется более тщательное расследование. @MarkSRasmussen может помочь нам с этим в следующий раз, когда он посетит.

Марк Стори-Смит
источник