Dies mag wie eine sehr grundlegende Frage erscheinen, und sollte es auch sein. Als Fan der wissenschaftlichen Methode erstelle ich jedoch gerne eine Hypothese und teste sie dann, um festzustellen, ob ich richtig bin. In diesem Fall versuche ich, die Ausgabe sys.dm_exec_sessions
und insbesondere die einzelne Spalte "liest" besser zu verstehen .
In den SQL Server-Onlinedokumenten wird dies eher trocken angegeben als:
Anzahl der Lesevorgänge, die von Anforderungen in dieser Sitzung während dieser Sitzung ausgeführt wurden. Ist nicht nullbar.
Man könnte annehmen, dass dies die Anzahl der von der Festplatte gelesenen Seiten angibt , um die von dieser Sitzung seit Beginn der Sitzung ausgegebenen Anforderungen zu erfüllen. Dies ist die Hypothese, von der ich dachte, ich würde sie testen.
Die logical_reads
Spalte in derselben Tabelle ist definiert als:
Anzahl der logischen Lesevorgänge, die in der Sitzung ausgeführt wurden. Ist nicht nullbar.
Aus Erfahrung mit SQL Server glaube ich, dass diese Spalte die Anzahl der Seiten widerspiegelt, die sowohl von der Festplatte als auch im Speicher gelesen wurden . Mit anderen Worten, die Gesamtzahl der Seiten, die jemals von der Sitzung gelesen wurden, unabhängig davon, wo sich diese Seiten befinden. Das Unterscheidungsmerkmal oder Wertversprechen, zwei separate Spalten zu haben, die ähnliche Informationen bieten, scheint darin zu bestehen, dass man das Verhältnis der von disk ( reads
) gelesenen Seiten zu den aus dem Puffercache ( ) gelesenen Seiten logical_reads
für eine bestimmte Sitzung verstehen kann .
Auf meinem Prüfstand habe ich eine neue Datenbank erstellt, eine einzelne Tabelle mit einer bekannten Anzahl von Datenseiten erstellt und diese Tabelle dann in einer neuen Sitzung gelesen. Dann schaute ich mir an, um sys.dm_exec_sessions
zu sehen, was die Spalten reads
und logical_reads
über die Sitzung sagten. An diesem Punkt bin ich durch die Ergebnisse verwirrt. Vielleicht kann mir hier jemand etwas Licht ins Dunkel bringen.
Der Prüfstand:
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;
Die erste Select-Anweisung oben zeigt, dass die Tabelle tatsächlich aus 10.000 Zeilen mit insgesamt 5.025 Seiten, 5.020 verwendeten Seiten und 5.000 Datenseiten besteht. genau wie man es erwarten würde:
Die zweite select-Anweisung bestätigt, dass für die TestReads
Tabelle nichts im Speicher ist .
In einer neuen Sitzung führen wir die folgende Abfrage durch, wobei wir die session_id notieren:
USE TestReads;
SET STATISTICS IO ON;
SELECT *
FROM dbo.TestReads;
Wie zu erwarten, liest dies die gesamte Tabelle von der Festplatte in den Speicher, wie in der Ausgabe von gezeigt 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.
In einer dritten Sitzung prüfen wir 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 */
Ich würde erwarten , um zu sehen , sys.dm_exec_sessions
zeigen mindestens 5.000 für beide reads
und logical_reads
. Leider sehe ich reads
zeigt Null. logical_reads
zeigt eine erwartete Anzahl von Lesevorgängen irgendwo nördlich von 5.000 - es zeigt 5.020 in meinem Test:
Ich weiß, dass SQL Server die gesamte TestReads
Tabelle aufgrund der sys_dm_os_buffer_descriptors
DMV in den Speicher eingelesen hat :
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;
Was mache ich falsch?
Ich verwende SQL Server 2012 11.0.5343 für diesen Test.
Weitere Ergebnisse:
Wenn ich Folgendes ausführe:
SELECT des.session_id
, des.reads
, des.logical_reads
FROM sys.dm_exec_sessions des
Ich sehe reads
784 in der Sitzung, in der ich den Prüfstand erstelle. Alle anderen Sitzungen zeigen jedoch Null in der reads
Spalte.
Ich habe jetzt meine SQL Server-Testinstanz auf 11.0.6020 aktualisiert. Das Ergebnis ist jedoch das gleiche.
SET STATISTICS IO ON
kurz bevor ich in der 2. Sitzung aus der Tabelle lese, werden 3 physische Lesevorgänge und 4998 Vorlesevorgänge gemeldet. sys.dm_exec_sessions
spiegelt dies jedoch immer noch nicht in der reads
Spalte wider .
STATISTICS IO
i.stack.imgur.com/XbHae.png
reads
Felder gesehen. Ich vermute, es funktioniert ähnlich wie die session_space_usage oder eine beliebige DMV, die die Tempdb-Nutzung pro Sitzung anzeigt und erst nach Abschluss der "Anfrage" erhöht wird.
sys.dm_exec_requests
Sie erhalten fast die gleichenset statistics io on
Ergebnisse.