Cela peut sembler une question très fondamentale, et ça devrait l'être. Cependant, en tant que fan de la méthode scientifique, j'aime créer une hypothèse, puis la tester pour voir si j'ai raison. Dans ce cas, j'essaie de mieux comprendre la sortie sys.dm_exec_sessions
, et plus précisément, la colonne unique "lit".
La documentation en ligne de SQL Server spécifie plutôt sèchement ceci:
Nombre de lectures effectuées, par requêtes dans cette session, au cours de cette session. N'est pas annulable.
On pourrait supposer que cela indiquerait le nombre de pages lues sur le disque pour satisfaire les demandes émises par cette session depuis le début de la session. C'est l'hypothèse que je pensais tester.
La logical_reads
colonne de cette même table est définie comme suit:
Nombre de lectures logiques effectuées sur la session. N'est pas annulable.
D'après mon expérience avec SQL Server, je pense que cette colonne reflète le nombre de pages qui ont été lues à la fois sur le disque et en mémoire . En d' autres termes, le nombre total de pages jamais lu par la session, peu importe où ces pages résident. Le différenciateur, ou proposition de valeur, d'avoir deux colonnes distinctes qui offrent des informations similaires semble être que l'on peut comprendre le rapport entre les pages lues sur le disque ( reads
) et celles lues dans le cache de tampon ( logical_reads
) pour une session spécifique.
Sur mon banc de test, j'ai créé une nouvelle base de données, créé une seule table avec un nombre connu de pages de données, puis lu cette table dans une nouvelle session. Ensuite, j'ai regardé sys.dm_exec_sessions
pour voir ce que les colonnes reads
et ont logical_reads
dit sur la session. À ce stade, je suis confus par les résultats. Peut-être que quelqu'un ici peut faire la lumière à ce sujet pour moi.
Le banc d'essai:
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;
Le premier énoncé de sélection ci-dessus montre qu'en fait, le tableau comprend 10 000 lignes, avec 5 025 pages au total, 5 020 pages utilisées et 5 000 pages de données; exactement comme on pourrait s'y attendre:
La deuxième instruction select confirme que nous n'avons rien en mémoire pour la TestReads
table.
Dans une nouvelle session , nous effectuons la requête suivante, en prenant note de la session_id:
USE TestReads;
SET STATISTICS IO ON;
SELECT *
FROM dbo.TestReads;
Comme on pouvait s'y attendre, cela lit la table entière du disque dans la mémoire, comme indiqué dans la sortie de 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.
Dans une troisième session, nous inspectons 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 */
Je m'attends à voir au moins 5 000 sys.dm_exec_sessions
spectacles pour et . Hélas, je vois montre zéro. montre un nombre attendu de lectures quelque part au nord de 5 000 - il montre 5 020 dans mon test:reads
logical_reads
reads
logical_reads
Je sais que SQL Server a lu la TestReads
table entière en mémoire, grâce au 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;
Qu'est-ce que je fais mal?
J'utilise SQL Server 2012 11.0.5343 pour ce test.
Autres constatations:
Si je lance ce qui suit:
SELECT des.session_id
, des.reads
, des.logical_reads
FROM sys.dm_exec_sessions des
Je vois reads
784 dans la session où je crée le banc d'essai; cependant, toutes les autres sessions affichent zéro dans la reads
colonne.
J'ai maintenant mis à jour mon instance de test SQL Server vers 11.0.6020; cependant le résultat est le même.
SET STATISTICS IO ON
juste avant de lire le tableau de la 2e session rapporte 3 lectures physiques et 4998 lectures anticipées; mais sys.dm_exec_sessions
ne reflète toujours pas cela dans la reads
colonne.
STATISTICS IO
i.stack.imgur.com/XbHae.png
reads
champs. Je soupçonne que cela fonctionne un peu comme session_space_usage ou tout autre DMV qui montre l'utilisation de tempdb par session qui n'augmente pas jusqu'à la fin de la "demande".
sys.dm_exec_requests
vous donnera presque les mêmesset statistics io on
résultats.