Ini mungkin tampak seperti pertanyaan yang sangat mendasar, dan memang seharusnya begitu. Namun, sebagai penggemar metode ilmiah, saya suka membuat hipotesis, kemudian mengujinya untuk melihat apakah saya benar. Dalam hal ini, saya mencoba untuk lebih memahami output sys.dm_exec_sessions
, dan lebih khusus, kolom tunggal "berbunyi".
SQL Server Books Online agak kering menetapkan ini sebagai:
Jumlah pembacaan yang dilakukan, berdasarkan permintaan dalam sesi ini, selama sesi ini. Tidak dapat dibatalkan.
Orang mungkin menganggap ini akan menunjukkan jumlah halaman yang dibaca dari disk untuk memenuhi permintaan yang dikeluarkan oleh sesi ini sejak awal sesi. Ini adalah hipotesis yang saya pikir akan saya uji.
The logical_reads
kolom di meja yang sama didefinisikan sebagai:
Jumlah pembacaan logis yang telah dilakukan pada sesi. Tidak dapat dibatalkan.
Dari pengalaman menggunakan SQL Server, saya percaya kolom ini mencerminkan jumlah halaman yang telah dibaca baik dari disk maupun di memori . Dengan kata lain, jumlah total halaman yang pernah dibaca oleh sesi, di mana pun halaman itu berada. Pembeda, atau nilai-proposisi, memiliki dua kolom terpisah yang menawarkan informasi serupa tampaknya adalah bahwa seseorang dapat memahami rasio halaman yang dibaca dari disk ( reads
) vs yang dibaca dari cache buffer ( logical_reads
) untuk sesi tertentu.
Di rig pengujian saya, saya telah membuat database baru, membuat tabel tunggal dengan jumlah halaman data yang diketahui, kemudian membaca tabel itu dalam sesi baru. Kemudian saya melihat sys.dm_exec_sessions
untuk melihat apa yang dikatakan kolom reads
dan logical_reads
tentang sesi. Pada titik ini saya bingung dengan hasilnya. Mungkin seseorang di sini dapat menjelaskan tentang hal ini untuk saya.
Rig uji:
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;
Pernyataan pilih pertama di atas menunjukkan bahwa sebenarnya tabel tersebut terdiri dari 10.000 baris, dengan 5.025 halaman total, 5.020 halaman yang digunakan, dan 5.000 halaman data; persis seperti yang diharapkan:
Pernyataan pilih kedua mengonfirmasi bahwa kami tidak memiliki apa pun di TestReads
tabel untuk memori .
Dalam sesi baru , kami melakukan kueri berikut, mencatat session_id:
USE TestReads;
SET STATISTICS IO ON;
SELECT *
FROM dbo.TestReads;
Seperti yang diharapkan, ini membaca seluruh tabel dari disk ke memori, seperti yang ditunjukkan pada output dari 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.
Dalam sesi ketiga , kami memeriksa 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 */
Saya berharap untuk melihat sys.dm_exec_sessions
pertunjukan setidaknya 5.000 untuk keduanya reads
dan logical_reads
. Sayangnya, saya melihat reads
menunjukkan nol. logical_reads
tidak menunjukkan jumlah pembacaan yang diharapkan di suatu tempat di utara 5.000 - ini menunjukkan 5.020 dalam pengujian saya:
Saya tahu SQL Server membaca seluruh TestReads
tabel ke dalam memori, berdasarkan 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;
Apa yang saya lakukan salah?
Saya menggunakan SQL Server 2012 11.0.5343 untuk tes ini.
Temuan lebih lanjut:
Jika saya menjalankan yang berikut ini:
SELECT des.session_id
, des.reads
, des.logical_reads
FROM sys.dm_exec_sessions des
Saya melihat reads
784 di sesi di mana saya membuat rig uji; namun semua sesi lainnya menunjukkan nol pada reads
kolom.
Saya sekarang telah memperbarui contoh pengujian SQL Server saya ke 11.0.6020; Namun hasilnya sama.
SET STATISTICS IO ON
sebelum saya membaca dari tabel pada sesi ke-2 melaporkan 3 membaca fisik, dan 4998 membaca-baca selanjutnya; Namun sys.dm_exec_sessions
masih tidak mencerminkan hal itu di reads
kolom.
STATISTICS IO
i.stack.imgur.com/XbHae.png
reads
bidang. Saya menduga ini berfungsi seperti session_space_usage atau DMV apa pun yang menunjukkan penggunaan tempdb per sesi yang tidak bertambah hingga "permintaan" selesai.
sys.dm_exec_requests
akan memberi Andaset statistics io on
hasil yang hampir sama .