Это может показаться очень простым вопросом, и так оно и должно быть. Однако, как поклонник научного метода, мне нравится создавать гипотезу, а затем проверять ее, чтобы убедиться, что я прав. В этом случае я пытаюсь лучше понять вывод 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; однако результат тот же.
SET STATISTICS IO ON
перед тем как я прочитал из таблицы во втором сеансе отчеты о 3 физических чтениях и 4998 чтениях с опережением чтения; Однако sys.dm_exec_sessions
все еще не отражает это в reads
столбце.
STATISTICS IO
i.stack.imgur.com/XbHae.png
reads
полей. Я подозреваю, что он работает так же, как session_space_usage или любой другой DMV, который показывает использование базы данных tempdb за сеанс, который не увеличивается до тех пор, пока «запрос» не завершится.
sys.dm_exec_requests
даст вам почти так же, какset statistics io on
результаты.