Đây có vẻ như là một câu hỏi rất cơ bản, và thực sự nó nên như vậy. Tuy nhiên, là một fan hâm mộ của phương pháp khoa học, tôi thích tạo ra một giả thuyết, sau đó kiểm tra nó để xem tôi có đúng không. Trong trường hợp này, tôi đang cố gắng hiểu rõ hơn về đầu ra sys.dm_exec_sessions
và cụ thể hơn là cột "đọc".
Sách SQL Server trực tuyến khá khô khan chỉ định điều này là:
Số lần đọc được thực hiện, theo yêu cầu trong phiên này, trong phiên này. Không phải là nullable.
Người ta có thể cho rằng điều này sẽ chỉ ra số lượng trang được đọc từ đĩa để đáp ứng các yêu cầu được đưa ra bởi phiên này kể từ khi bắt đầu phiên. Đây là giả thuyết tôi nghĩ tôi muốn thử nghiệm.
Các logical_reads
cột ở chỗ cùng một bảng được định nghĩa là:
Số lần đọc logic đã được thực hiện trên phiên. Không phải là nullable.
Từ kinh nghiệm sử dụng SQL Server, tôi tin rằng cột này phản ánh số lượng trang đã được đọc cả từ đĩa và trong bộ nhớ . Nói cách khác, tổng số trang từng được đọc bởi phiên, bất kể các trang đó nằm ở đâu. Sự khác biệt, hoặc đề xuất giá trị, có hai cột riêng biệt cung cấp thông tin tương tự nhau dường như có thể hiểu tỷ lệ các trang đọc từ đĩa ( reads
) so với các trang được đọc từ bộ đệm bộ đệm ( logical_reads
) cho một phiên cụ thể.
Trên thiết bị thử nghiệm của tôi, tôi đã tạo một cơ sở dữ liệu mới, tạo một bảng duy nhất với số lượng trang dữ liệu đã biết, sau đó đọc bảng đó trong một phiên mới. Sau đó, tôi nhìn vào sys.dm_exec_sessions
để xem những gì reads
và logical_reads
cột nói về phiên. Tại thời điểm này tôi bị bối rối bởi kết quả. Có lẽ ai đó ở đây có thể làm sáng tỏ điều này cho tôi.
Giàn khoan thử nghiệm:
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;
Câu lệnh chọn đầu tiên ở trên cho thấy trên thực tế, bảng này bao gồm 10.000 hàng, với tổng số 5.025 trang, 5.020 trang được sử dụng và 5.000 trang dữ liệu; chính xác như người ta mong đợi:
Câu lệnh chọn thứ hai xác nhận chúng ta không có gì trong bộ nhớ cho TestReads
bảng.
Trong phiên mới , chúng tôi thực hiện truy vấn sau, lưu ý đến session_id:
USE TestReads;
SET STATISTICS IO ON;
SELECT *
FROM dbo.TestReads;
Như mọi người mong đợi, cái này đọc toàn bộ bảng từ đĩa vào bộ nhớ, như thể hiện trong đầu ra từ 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.
Trong phiên thứ ba , chúng tôi kiểm tra 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 */
Tôi hy vọng sẽ thấy sys.dm_exec_sessions
chương trình ít nhất 5.000 cho cả hai reads
và logical_reads
. Than ôi, tôi thấy reads
cho thấy không. logical_reads
không hiển thị số lần đọc dự kiến ở đâu đó ở phía bắc 5.000 - nó hiển thị 5.020 trong thử nghiệm của tôi:
Tôi biết SQL Server đọc toàn bộ TestReads
bảng vào bộ nhớ, nhờ vào 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;
Tôi đang làm gì sai?
Tôi đang sử dụng SQL Server 2012 11.0.5343 cho bài kiểm tra này.
Phát hiện thêm:
Nếu tôi chạy như sau:
SELECT des.session_id
, des.reads
, des.logical_reads
FROM sys.dm_exec_sessions des
Tôi thấy reads
784 trong phiên tôi đang tạo giàn thử; tuy nhiên tất cả các phiên khác hiển thị số không trong reads
cột.
Bây giờ tôi đã cập nhật phiên bản thử nghiệm SQL Server của mình lên 11.0.6020; tuy nhiên kết quả là như nhau.
SET STATISTICS IO ON
ngay trước khi tôi đọc từ bảng trong phiên thứ 2 báo cáo 3 lần đọc vật lý và 4998 lần đọc trước; tuy nhiên sys.dm_exec_sessions
vẫn không phản ánh điều đó trong reads
cột.
STATISTICS IO
i.stack.imgur.com/XbHae.png
reads
lĩnh vực. Tôi nghi ngờ nó hoạt động giống như session_space_usage hoặc bất kỳ DMV nào hiển thị mức sử dụng tempdb cho mỗi phiên không tăng cho đến khi "yêu cầu" kết thúc.
sys.dm_exec_requests
sẽ cho bạn gần giống nhưset statistics io on
kết quả.