Это может показаться очень простым вопросом, и так оно и должно быть. Однако, как поклонник научного метода, мне нравится создавать гипотезу, а затем проверять ее, чтобы убедиться, что я прав. В этом случае я пытаюсь лучше понять вывод sys.dm_exec_sessions
, а точнее, один столбец «читает».
Электронная документация по SQL Server довольно сухо определяет это как:
Количество операций чтения, выполненных по запросам в этом сеансе, в течение этого сеанса. Не обнуляется.
Можно предположить, что это будет указывать количество страниц, прочитанных с диска, чтобы удовлетворить запросы, выданные этим сеансом с начала сеанса. Это гипотеза, которую я думал проверить.
logical_reads
Столбец в той же таблице, определяется как:
Количество логических чтений, выполненных в сеансе. Не обнуляется.
Исходя из опыта использования SQL Server, я считаю, что этот столбец отражает количество страниц, которые были прочитаны как с диска, так и в памяти . Другими словами, общее количество страниц , когда - либо читать сессии, независимо от того , где эти страницы проживаете. Дифференцирующие, или стоимость предложение, из двух отдельных столбцов , которые предлагают подобную информацию будет , кажется , что что можно понять отношение прочитанных страниц с диска ( reads
) против тех чтения из буфера кэша ( logical_reads
) для конкретной сессии.
На своем тестовом стенде я создал новую базу данных, создал одну таблицу с известным количеством страниц данных, а затем прочитал эту таблицу в новом сеансе. Затем я посмотрел, sys.dm_exec_sessions
чтобы увидеть, что reads
и logical_reads
колонки говорят о сессии. На данный момент я смущен результатами. Возможно, кто-то здесь может пролить свет на это для меня.
Испытательная установка:
USE master;
IF EXISTS (SELECT 1
FROM sys.databases d
WHERE d.name = 'TestReads')
BEGIN
ALTER DATABASE TestReads SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE TestReads;
END
GO
CREATE DATABASE TestReads;
GO
ALTER DATABASE TestReads SET RECOVERY SIMPLE;
BACKUP DATABASE TestReads TO DISK = 'NUL:'; /* ensure we are in
simple recovery model */
GO
USE TestReads;
GO
/*
create a table with 2 rows per page, for easy math!
*/
CREATE TABLE dbo.TestReads
(
ID INT NOT NULL
CONSTRAINT PK_TestReads
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, SomeData CHAR(4000) NOT NULL
);
/*
insert 5000 pages of data
*/
INSERT INTO dbo.TestReads (SomeData)
SELECT TOP(10000) o1.name
FROM sys.objects o1
, sys.objects o2
, sys.objects o3
ORDER BY o1.object_id
, o2.object_id
, o3.object_id;
/*
Verify we have 5,000 pages of data, with 10,000 rows.
*/
SELECT o.name
, p.rows
, au.total_pages
, au.used_pages
, au.data_pages
FROM sys.partitions p
INNER JOIN sys.objects o ON p.object_id = o.object_id
INNER JOIN sys.allocation_units au
ON p.hobt_id = au.container_id
AND (au.type = 1 or au.type = 0)
WHERE p.index_id = 1
AND o.name = 'TestReads'
AND o.type = 'U';
/*
issue a checkpoint to ensure dirty pages are flushed to disk
*/
CHECKPOINT 30;
DBCC DROPCLEANBUFFERS;
DBCC FREESYSTEMCACHE ('ALL');
DBCC FREEPROCCACHE;
DBCC FREESESSIONCACHE;
GO
/*
ensure we have no data cached in memory for the TestReads database
*/
USE master;
ALTER DATABASE TestReads SET OFFLINE WITH ROLLBACK IMMEDIATE;
ALTER DATABASE TestReads SET ONLINE;
SELECT DatabaseName = d.name
, SchemaName = s.name
, ObjectName = o.name
, AllocatedMB = COUNT(1) * 8192E0 / 1048576
, PagesInMemory = COUNT(1)
FROM sys.dm_os_buffer_descriptors dobd
INNER JOIN sys.allocation_units au
ON dobd.allocation_unit_id = au.allocation_unit_id
INNER JOIN sys.partitions p
ON au.container_id = p.hobt_id
AND (au.type = 1 OR au.type = 0)
INNER JOIN sys.objects o ON p.object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN sys.databases d
ON dobd.database_id = d.database_id
WHERE d.name = 'TestReads'
AND o.name = 'TestReads'
AND o.type = 'U'
GROUP BY d.name
, s.name
, o.name;
Первый оператор select выше показывает, что на самом деле таблица состоит из 10 000 строк, с общим количеством страниц 5 025, 5 020 используемых страниц и 5 000 страниц данных; именно так, как и следовало ожидать:
Второй оператор select подтверждает, что у нас ничего нет в памяти для TestReads
таблицы.
В новом сеансе мы делаем следующий запрос, принимая к сведению идентификатор_сессии:
USE TestReads;
SET STATISTICS IO ON;
SELECT *
FROM dbo.TestReads;
Как и следовало ожидать, это читает всю таблицу с диска в память, как показано в выводе из SET STATISTICS IO ON
:
(10000 row(s) affected)
Table 'TestReads'. Scan count 1, logical reads 5020, physical reads 3,
read-ahead reads 4998, lob logical reads 0, lob physical reads 0, lob
read-ahead reads 0.
На третьей сессии мы проверяем sys.dm_exec_sessions
:
SELECT des.session_id
, des.reads
, des.logical_reads
FROM sys.dm_exec_sessions des
WHERE des.session_id = 57; /* session_id from the 2nd (previous) session */
Я ожидаю увидеть sys.dm_exec_sessions
шоу по крайней мере 5000 для обоих reads
и logical_reads
. Увы, я вижу, reads
показывает ноль. logical_reads
действительно показывает ожидаемое число чтений где-то к северу от 5000 - в моем тесте это показывает 5,020:
Я знаю, что SQL Server считал всю TestReads
таблицу в память благодаря sys_dm_os_buffer_descriptors
DMV:
USE TestReads;
GO
SELECT DatabaseName = d.name
, SchemaName = s.name
, ObjectName = o.name
, AllocatedMB = COUNT(1) * 8192E0 / 1048576
, PagesInMemory = COUNT(1)
FROM sys.dm_os_buffer_descriptors dobd
INNER JOIN sys.allocation_units au
ON dobd.allocation_unit_id = au.allocation_unit_id
INNER JOIN sys.partitions p
ON au.container_id = p.hobt_id
AND (au.type = 1 OR au.type = 0)
INNER JOIN sys.objects o ON p.object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN sys.databases d
ON dobd.database_id = d.database_id
WHERE d.name = 'TestReads'
AND o.name = 'TestReads'
AND o.type = 'U'
GROUP BY d.name
, s.name
, o.name;
Что я делаю неправильно?
Я использую SQL Server 2012 11.0.5343 для этого теста.
Дальнейшие выводы:
Если я запускаю следующее:
SELECT des.session_id
, des.reads
, des.logical_reads
FROM sys.dm_exec_sessions des
Я вижу reads
784 на сессии, где я создаю испытательный стенд; однако все остальные сеансы показывают ноль в reads
столбце.
Теперь я обновил свой тестовый экземпляр SQL Server до 11.0.6020; однако результат тот же.
источник
sys.dm_exec_requests
даст вам почти так же, какset statistics io on
результаты.SET STATISTICS IO ON
перед тем как я прочитал из таблицы во втором сеансе отчеты о 3 физических чтениях и 4998 чтениях с опережением чтения; Однакоsys.dm_exec_sessions
все еще не отражает это вreads
столбце.STATISTICS IO
i.stack.imgur.com/XbHae.pngreads
полей. Я подозреваю, что он работает так же, как session_space_usage или любой другой DMV, который показывает использование базы данных tempdb за сеанс, который не увеличивается до тех пор, пока «запрос» не завершится.Ответы:
Я всегда понимал, что
reads
это только физическое (т.е. с диска) иlogical_reads
только из пула буферов (то есть из памяти). Я провел быстрый тест с меньшей таблицей, в которой всего 2 страницы данных и всего 3 страницы, и то, что я вижу, похоже, подтверждает эти два определения.Одна вещь, которая, вероятно, дает вам плохие результаты, это то, что вы не очищаете память. Вы должны запустить следующее между тестами, чтобы перезагрузить его с диска:
Моя тестовая установка была просто следующей:
Затем я запустил следующее:
(Да, я проводил тестирование в том же сеансе, в котором выполнял DMV, но это не исказило результаты для
reads
поля, и, если не сказать ничего другого, было, по крайней мере, последовательным, если оно внесло вклад вlogical_reads
поле.)Для тестирования я запускаю команду DBCC, а затем два запроса SELECT. Тогда я бы увидел скачок как в поле, так
reads
и вlogical_reads
поле. Я бы снова запустил запросы SELECT, а иногда увидел бы дополнительный переходreads
.После этого я выполняю два запроса SELECT много раз, и
reads
они остаются неизменными, в то время как значениеlogical_reads
увеличивается на 4 каждый раз.Затем я бы начал с запуска DBCC и увидел бы тот же шаблон. Я делал это довольно много раз, и сообщенные цифры были одинаковыми во всех тестовых прогонах.
Больше информации:
Я также тестирую на SQL Server 2012, SP2 - 64 бит (11.0.5343).
Следующие команды DBCC, которые мы оба пробовали и не видели никакого эффекта:
Большую часть времени
DBCC DROPCLEANBUFFERS
работает, но я иногда вижу, что он все еще находится в буферном пуле. Странный.Когда я:
DBCC DROPCLEANBUFFERS
: Чтения увеличиваются на 24, а логические чтения увеличиваются на 52.SELECT [Col1] FROM dbo.ReadTest;
снова: чтения не увеличиваются, но логические_читки увеличиваются на 6.DBCC DROPCLEANBUFFERS
).Похоже, что 52 логических чтения учитывают генерацию плана и результаты, что подразумевает, что генерация плана вызвала дополнительные 46 логических чтений. Но физические чтения не повышаются снова, и все же это те же 52 логических чтения, которые были, когда это было необходимо, чтобы также выполнить физические чтения, следовательно
logical_reads
, не включает в себя физические чтенияreads
. Я просто разъясняю этот момент, независимо от того, было ли это указано или подразумевается в Вопросе.НО, одно поведение, которое я заметил, сбрасывает (хотя бы немного) с использованием существования страниц данных таблицы
sys.dm_os_buffer_descriptors
: она перезагружается каким-то другим процессом. Если вы DROPCLEANBUFFERS и проверьте сразу, то это должно быть пропало. Но подождите несколько минут, и он появится снова, но на этот раз без всех страниц данных. В моем тесте таблица имеет 1 страницу IAM и 4 страницы данных. Все 5 страниц находятся в пуле буферов после того, как я сделаюSELECT
. Но когда он перезагружается каким-то другим процессом, это просто страница IAM и 1 страница данных. Я думал, что это может быть SSMS IntelliSense, но я удалил все ссылки на это имя объекта на моей вкладке запроса, и он все еще перезагружается.источник
DBCC DROPCLEANBUFFERS
(и другиеDBCC DROPxxx
команды) из моей тестовой установки, потому что они не имели никакого значения. При отключении базы данных все буферы удаляются, а все остальное связывается с базой данных.DBCC FREESYSTEMCACHE ('ALL'); DBCC FREEPROCCACHE; DBCC FREESESSIONCACHE;
CHECKPOUNT
в контексте базы данных доDBCC DROPCLEANBUFFERS
.