sys.dm_exec_sessionsの「reads」列は実際には何を示していますか?


10

これは非常に基本的な質問のように思えるかもしれませんが、実際にそうである必要があります。ただし、科学的手法のファンとして、私は仮説を立て、それをテストして自分が正しいかどうかを確認するのが好きです。この場合、私はの出力sys.dm_exec_sessions、より具体的には、単一列の「読み取り」をよりよく理解しようとしています。

SQL Server Books Onlineでは、これを次のように明確に指定しています。

このセッション中に、このセッションのリクエストによって実行された読み取りの数。null可能ではありません。

これは、セッションの開始以降、このセッションによって発行された要求を満たすためにディスクから読み取られたページの数を示していると考えられます。これは私がテストしようと思った仮説です。

logical_reads同じテーブルの列は次のように定義されます。

セッションで実行された論理読み取りの数。null可能ではありません。

SQL Serverの使用経験から、この列はディスクメモリの両方から読み取られたページ数を反映していると思います。つまり、ページがどこにあるかに関係なく、セッションでこれまでに読み取られたページの総数です。同様の情報を提供する2つの別々の列を持つことの差別化要因、つまり価値命題は、特定のセッションでディスクから読み取られたページ()とバッファキャッシュから読み取られたページ()の比率を理解できるように思われるでしょう。readslogical_reads

私のテストリグでは、新しいデータベースを作成し、既知のページ数のデータを含む単一のテーブルを作成してから、新しいセッションでそのテーブルを読み取りました。次にsys.dm_exec_sessionsreadsとの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 TestReadssys_dm_os_buffer_descriptorsDMVのおかげでテーブル全体をメモリに読み込むことを知っています。

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_requestsset statistics io on結果とほぼ同じになります。
Kin Shah

1
SET STATISTICS IO ON2番目のセッションでテーブルから読み取る直前に興味深いのは、3つの物理読み取りと4998の先読み読み取りを報告しています。ただしsys.dm_exec_sessionsreads列にはまだ反映されていません。
Max Vernon、

2
2012年、STATISTICS IO i.stack.imgur.com / XbHae.png
Martin Smith

1
実際、私は2008年からSQL2016CTP3までテストしたすべてのエディションで私のアプローチで両方の列をゼロにしています
Martin Smith

1
@MartinSmithとMax:readsフィールドのインクリメントの一部で遅延が発生しています。これは、session_space_usageまたはセッションごとのtempdbの使用状況を示すDMVとほぼ同じように機能し、「リクエスト」が完了するまで増加しないと思います。
ソロモンRutzky

回答:


2

私の理解では、これは常にreads物理的なもの(つまりディスクから)でありlogical_reads、バッファプールから(つまりメモリから)だけのものでした。データページが2つ、合計が3ページしかない小さなテーブルで簡単なテストを行ったところ、2つの定義が確認できたようです。

おそらくあなたに悪い結果をもたらしていることの1つは、あなたがメモリをクリアしていないということです。テスト間で次のコマンドを実行して、ディスクから強制的にリロードする必要があります。

DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;

私のテストセットアップは次のとおりです。

CREATE TABLE dbo.ReadTest (Col1 CHAR(7500) DEFAULT (' '));
INSERT INTO dbo.ReadTest (Col1) VALUES (DEFAULT), (DEFAULT);

次に、以下を実行しました。

SELECT reads, logical_reads FROM sys.dm_exec_sessions WHERE session_id = @@SPID;
SELECT * FROM dbo.ReadTest;

(はい、DMVを実行しているのと同じセッションでテストしていましたが、readsフィールドの結果を歪めませんでした。それ以外に、logical_readsフィールドに貢献していたとしても、少なくとも一貫性がありました。)

テストでは、DBCCコマンドを実行してから、2つのSELECTクエリを実行します。次にreadslogical_readsフィールドとフィールドの両方でジャンプが表示されます。SELECTクエリを再度実行すると、追加のジャンプが表示されることがありますreads

その後、私は2つのSELECTクエリを何度も実行しましたreadsが、がlogical_reads毎回4ずつ増加する間は同じままです。

次に、DBCCの実行からやり直して、同じパターンを確認します。私はこれをかなり何度も行い、報告された数値はすべてのテスト実行で一貫していた。


より詳しい情報:

SQL Server 2012、SP2-64ビット(11.0.5343)でもテストしています。

次のDBCCコマンドは、試行したが効果はありません。

DBCC FREESYSTEMCACHE('ALL');
DBCC FREEPROCCACHE;
DBCC FREESESSIONCACHE;

ほとんどのDBCC DROPCLEANBUFFERS場合は機能しますが、それがまだバッファプールにあることがときどきあります。奇数。

私が:

  • DBCC DROPCLEANBUFFERS:読み取りは24増加し、logical_readsは52増加します。
  • SELECT [Col1] FROM dbo.ReadTest;再実行:読み取りは増えませんが、logical_readsは6ずつ増えます。
  • クエリテキストにスペースを追加して再実行します。読み取りは増えませんが、logical_readsは52増加します(の直後と同様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コマンド)を削除しました。データベースをオフラインに設定すると、すべてのバッファ、およびデータベースに関連付けられているその他すべてが削除されます。
Max Vernon

私はあなたと同じように物理的な読み取りについて理解していました。論理的な読み取りはバッファプールから始まります。
Max Vernon

私も試してみました: DBCC FREESYSTEMCACHE ('ALL'); DBCC FREEPROCCACHE; DBCC FREESESSIONCACHE;
Max Vernon

1
@MaxVernonは "keep 'em guessin"機能になる可能性があります;-)
ソロモンRutzky

2
@MaxVernon、のCHECKPOUNT前にデータベースコンテキストでを実行することを忘れないでくださいDBCC DROPCLEANBUFFERS
Dan Guzman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.