これは非常に基本的な質問のように思えるかもしれませんが、実際にそうである必要があります。ただし、科学的手法のファンとして、私は仮説を立て、それをテストして自分が正しいかどうかを確認するのが好きです。この場合、私はの出力sys.dm_exec_sessions
、より具体的には、単一列の「読み取り」をよりよく理解しようとしています。
SQL Server Books Onlineでは、これを次のように明確に指定しています。
このセッション中に、このセッションのリクエストによって実行された読み取りの数。null可能ではありません。
これは、セッションの開始以降、このセッションによって発行された要求を満たすためにディスクから読み取られたページの数を示していると考えられます。これは私がテストしようと思った仮説です。
logical_reads
同じテーブルの列は次のように定義されます。
セッションで実行された論理読み取りの数。null可能ではありません。
SQL Serverの使用経験から、この列はディスクとメモリの両方から読み取られたページ数を反映していると思います。つまり、ページがどこにあるかに関係なく、セッションでこれまでに読み取られたページの総数です。同様の情報を提供する2つの別々の列を持つことの差別化要因、つまり価値命題は、特定のセッションでディスクから読み取られたページ()とバッファキャッシュから読み取られたページ()の比率を理解できるように思われるでしょう。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データページであることを示しています。期待どおりに:
2番目のselectステートメントは、TestReads
テーブルのメモリに何もないことを確認します。
で新しいセッション、我々はSESSION_IDのノートを取って、次のクエリを実行します。
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
予想される読み取り数が5,000の北にあることを示しています-私のテストでは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
2番目のセッションでテーブルから読み取る直前に興味深いのは、3つの物理読み取りと4998の先読み読み取りを報告しています。ただしsys.dm_exec_sessions
、reads
列にはまだ反映されていません。
STATISTICS IO
i.stack.imgur.com / XbHae.png
reads
フィールドのインクリメントの一部で遅延が発生しています。これは、session_space_usageまたはセッションごとのtempdbの使用状況を示すDMVとほぼ同じように機能し、「リクエスト」が完了するまで増加しないと思います。
sys.dm_exec_requests
set statistics io on
結果とほぼ同じになります。