sys.dm_exec_sessions의“읽기”열은 실제로 무엇을 나타 냅니까?


10

이것은 매우 기본적인 질문처럼 보일 수 있으며 실제로 그렇습니다. 그러나 과학적 방법의 팬으로서 나는 가설을 만들고 테스트하여 내가 맞는지 테스트합니다. 이 경우, sys.dm_exec_sessions보다 구체적으로 단일 열 "읽기" 의 출력을 더 잘 이해하려고합니다 .

SQL Server 온라인 설명서에서는이를 다음과 같이 건조하게 지정합니다.

이 세션 동안이 세션의 요청에 의해 수행 된 읽기 수 널 입력 가능하지 않습니다.

세션 시작 이후이 세션이 발행 한 요청을 충족시키기 위해 디스크에서 읽은 페이지 수를 표시한다고 가정 할 수 있습니다 . 이것이 제가 테스트 할 것이라고 생각한 가설입니다.

logical_reads같은 테이블 의 열은 다음과 같이 정의됩니다.

세션에서 수행 된 논리적 읽기 수입니다. 널 입력 가능하지 않습니다.

SQL Server 사용 경험을 바탕으로이 열 은 디스크메모리 에서 읽은 페이지 수를 반영한다고 생각합니다 . 즉, 총 페이지 수는 세션, 해당 페이지가 존재 상관없이 읽을. 비슷한 정보를 제공하는 두 개의 별도 열을 갖는 차별화 요소 또는 가치 제안 은 특정 세션에 대해 디스크에서 읽은 페이지 와 버퍼 캐시에서 읽은 페이지의 비율을 이해할 수있는 것으로 보입니다 .readslogical_reads

테스트 장비에서 새 데이터베이스를 만들고 알려진 페이지 수의 데이터로 단일 테이블을 만든 다음 새 세션에서 해당 테이블을 읽습니다. 그런 다음 세션에 대해 및 열의 sys.dm_exec_sessions내용을 확인했습니다 . 이 시점에서 나는 결과에 혼란스러워한다. 아마 여기 누군가가 나를 위해 이것에 대해 약간의 빛을 비출 수 있습니다.readslogical_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테이블에 대한 메모리가 없음을 확인 합니다.

A의 새로운 세션 , 우리는 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.

A의 세 번째 세션, 우리는 검사 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 */

과에 대해 5,000 회 이상sys.dm_exec_sessions 표시 될 것으로 예상됩니다 . 아아, 나는 0을 보여준다. 5,000의 북쪽 어딘가에 예상되는 읽기 수를 보여줍니다-내 테스트에서 5,020을 보여줍니다.readslogical_readsreadslogical_reads

여기에 이미지 설명을 입력하십시오

DMV TestReads덕분에 SQL Server가 전체 테이블을 메모리로 읽은 것을 알고 있습니다 sys_dm_os_buffer_descriptors.

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열에 0으로 표시 됩니다.

이제 SQL Server 테스트 인스턴스를 11.0.6020으로 업데이트했습니다. 그러나 결과는 같습니다.


sys.dm_exec_requestsset statistics io on결과 와 거의 동일 합니다.
Kin Shah

1
SET STATISTICS IO ON두 번째 세션의 표에서 읽기 직전에 흥미로운 것은 3 개의 물리적 읽기와 4998 개의 미리 읽기를 나타냅니다. 그러나 sys.dm_exec_sessions여전히 reads열에 반영하지 않습니다 .
Max Vernon

2
모두 읽기 및 논리적에서보고 된 비 제로 결과에도 불구하고 읽고 2012 년에 나는 자주 공을보고 있어요 STATISTICS IO i.stack.imgur.com/XbHae.png
마틴 스미스

1
실제로 2008 년부터 SQL2016CTP3까지 테스트 한 모든 에디션에 대한 접근 방식으로 두 열이 모두 0 인 것을 볼 수 있습니다
Martin Smith

1
@ MartinSmith와 Max : 나는 또한 reads필드 의 증가에 약간의 지연을 보았습니다 . "요청"이 끝날 때까지 증가하지 않는 세션 당 tempdb 사용량을 나타내는 session_space_usage 또는 다른 DMV와 매우 유사하게 작동합니다.
Solomon Rutzky

답변:


2

내 이해는 항상 reads물리적 (즉, 디스크)이고 logical_reads버퍼 풀 (예 : 메모리)에서만 있다는 것입니다. 나는 2 개의 데이터 페이지와 3 개의 페이지 만있는 작은 테이블로 빠른 테스트를 수행했으며, 내가보고있는 것은이 두 가지 정의를 확인하는 것으로 보입니다.

아마도 나쁜 결과를 낳을 수있는 한 가지는 메모리를 지우지 않는 것입니다. 디스크에서 강제로 다시로드하려면 테스트간에 다음을 실행해야합니다.

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 명령을 실행 한 다음 두 개의 SELECT 쿼리를 실행합니다. 그럼 모두에서 점프 볼 것이다 readslogical_reads필드. SELECT 쿼리를 다시 실행하고 때로는 추가 점프가 표시되는 경우가 있습니다 reads.

그 후 두 개의 SELECT 쿼리를 여러 번 실행하고 매번 4 씩 증가하는 reads동안 동일하게 유지 logical_reads됩니다.

그런 다음 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명령)을 제거 했지만 아무런 차이가 없었습니다. 데이터베이스를 오프라인으로 설정하면 모든 버퍼 및 데이터베이스와 관련된 다른 모든 항목이 삭제됩니다.
맥스 버논

나는 물리적 인 읽기에 대해 당신과 같은 이해를하고 있었고 논리적 읽기는 버퍼 풀 btw에서 시작합니다.
Max Vernon

나는 또한 그것을 시도했다 : DBCC FREESYSTEMCACHE ('ALL'); DBCC FREEPROCCACHE; DBCC FREESESSIONCACHE;
맥스 버논

1
@MaxVernon "계속 추측"기능이 될 수 있습니다 ;-)
Solomon Rutzky

2
@MaxVernon CHECKPOUNT은 데이터베이스 컨텍스트에서 를 실행하는 것을 잊지 마십시오 DBCC DROPCLEANBUFFERS.
Dan Guzman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.