นี่อาจดูเหมือนคำถามพื้นฐานมากและแน่นอนควรเป็นเช่นนั้น อย่างไรก็ตามในฐานะแฟนของวิธีการทางวิทยาศาสตร์ฉันชอบที่จะสร้างสมมติฐานแล้วทดสอบเพื่อดูว่าฉันถูกต้อง ในกรณีนี้ฉันพยายามทำความเข้าใจกับผลลัพธ์ของsys.dm_exec_sessions
และโดยเฉพาะคอลัมน์ "อ่าน"
SQL Server Books Online ค่อนข้างจะระบุว่าเป็น:
จำนวนการอ่านที่ดำเนินการตามคำขอในเซสชันนี้ในระหว่างเซสชันนี้ ไม่เป็นโมฆะ
หนึ่งอาจสันนิษฐานว่าสิ่งนี้จะบ่งบอกถึงจำนวนหน้าอ่านจากดิสก์เพื่อตอบสนองการร้องขอที่ออกโดยเซสชั่นนี้ตั้งแต่เริ่มต้นของเซสชั่น นี่คือสมมติฐานที่ฉันคิดว่าฉันจะทดสอบ
logical_reads
คอลัมน์ในตารางเดียวกันกับที่มีการกำหนดเป็น:
จำนวนการอ่านโลจิคัลที่ดำเนินการบนเซสชัน ไม่เป็นโมฆะ
จากประสบการณ์ที่ใช้ SQL Server ผมเชื่อว่าคอลัมน์นี้สะท้อนให้เห็นถึงจำนวนของหน้าเว็บที่ได้รับการอ่านทั้งจากดิสก์และในหน่วยความจำ กล่าวอีกนัยหนึ่งจำนวนหน้าทั้งหมดที่เคยอ่านจากเซสชันไม่ว่าหน้านั้นจะอยู่ที่ใด ความแตกต่างหรือข้อเสนอคุณค่าของการมีสองคอลัมน์แยกต่างหากที่ให้ข้อมูลที่คล้ายกันดูเหมือนจะเป็นที่หนึ่งที่สามารถเข้าใจอัตราส่วนของหน้าอ่านจากดิสก์ ( 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;
คำสั่งเลือกแรกข้างต้นแสดงให้เห็นว่าในความเป็นจริงตารางประกอบด้วย 10,000 แถวโดยมีหน้าทั้งหมด 5,025 หน้าใช้ 5,020 หน้าและหน้าข้อมูล 5,000 หน้า แม่นยำอย่างที่คาดหวัง:
คำสั่ง 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
การแสดงอย่างน้อย 5,000 สำหรับทั้งสองและ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 หรือ DMV ใดก็ตามที่แสดงการใช้ tempdb ต่อเซสชันที่ไม่เพิ่มขึ้นจนกว่า "คำขอ" จะเสร็จสิ้น
sys.dm_exec_requests
จะให้set statistics io on
ผลลัพธ์เกือบเหมือนกัน