我最近一直在查看一些 SQL Profiler 跟踪记录,我看到了一些我不明白的东西。我正在运行简单的 INSERT 命令:
INSERT INTO Foo (ForeignID, FileExtension, MimeType) VALUES (1, 'FOO', 'Application/Foo')
Run Code Online (Sandbox Code Playgroud)
SQL Profiler 始终显示 0 次写入和 2 次读取。INSERT 上怎么可能没有任何写入?还是我误解了分析器在说什么?
为了完整起见,这是我正在使用的表定义:
CREATE TABLE [Foo](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ForeignID] [int] NOT NULL,
[FileExtension] [nvarchar](32) NOT NULL,
[MimeType] [nvarchar](96) NOT NULL,
CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
Profiler写入列记录为
服务器代表事件执行的物理磁盘写入次数。
在提交事务之前,必须将日志物理写入磁盘,但这些写入不会包含在 Profiler 报告的写入统计中。
对于许多插入,在语句完成之前可能不会发生物理写入,因为页面在缓冲区缓存中被修改并且直到稍后才写出到磁盘(例如通过检查点或惰性写入器进程)。
对于批量插入,有一个急切的写入器,因此页面可能会在之前写出到磁盘。有关更多信息,请参阅在 BOL 中编写页面。
然而,以上似乎并不相关,因为即使没有页面写入磁盘,物理写入也可以报告为非零。
在下面的测试中,Profiler 报告了 5 次插入写入,但使用进程监视器监视文件写入并sys.dm_io_virtual_file_stats
显示实际上没有发生。从中我得出结论,物理写入列实际上显示了变脏的页面数(理由是这些页面稍后需要写出到磁盘)
因此,基于该假设,SQL Profiler 在您的测试中显示 0 Writes,因为您正在插入一个已经脏的页面。
TRUNCATE TABLE Foo
CHECKPOINT;
DBCC DROPCLEANBUFFERS;
/*Returns 0 rows*/
SELECT *
FROM sys.dm_os_buffer_descriptors
WHERE database_id = DB_ID()
AND is_modified = 1
SELECT 'Before Insert', num_of_writes, num_of_bytes_written
FROM sys.dm_io_virtual_file_stats(db_id(), 1)
INSERT INTO Foo
(ForeignID,
FileExtension,
MimeType)
VALUES ( 1,
'FOO',
'Application/Foo')
/*Nothing Written. Figures same as previous query*/
SELECT 'After Insert', num_of_writes, num_of_bytes_written
FROM sys.dm_io_virtual_file_stats(db_id(), 1)
/*Returns 5 rows*/
SELECT *
FROM sys.dm_os_buffer_descriptors
WHERE database_id = DB_ID()
AND is_modified = 1
CHECKPOINT;
/*Shows physical writes*/
SELECT 'After Checkpoint', num_of_writes, num_of_bytes_written
FROM sys.dm_io_virtual_file_stats(db_id(), 1)
Run Code Online (Sandbox Code Playgroud)
CHECKPOINT
所以 CheckPoint 实际上实际写了 8 个页面(6 个单页和 1 个双页),但在 Profiler 中显示为只负责 4 个。
从进程监视器屏幕截图中的偏移量,可以准确地看到哪些页面被写入
+-----+---------------+-----------+
| 57 | syscolpars | DATA_PAGE |
| 86 | sysrscols | DATA_PAGE |
| 93 | sysrowsets | DATA_PAGE |
| 143 | sysallocunits | DATA_PAGE |
| 168 | Foo | DATA_PAGE |
| 169 | Foo | IAM_PAGE |
| 1 | | PFS_PAGE |
| 9 | | BOOT_PAGE |
+-----+---------------+-----------+
Run Code Online (Sandbox Code Playgroud)
输出中未显示的另外三个页面dm_os_buffer_descriptors
是数据库引导页面和sysrscols
, sysrowsets
。
CHECKPOINT
随着dbi_checkptLSN
字段的更新,数据库引导页的写入与自身相关。
预计插入会导致其他两个页面被更新(分别为Thercmodified
和rcrows
列),但这似乎不会立即发生,而且我LOP_COUNT_DELTA
在日志文件中也看不到任何 条目,所以我认为这必须定期发生,而不是在之后发生每一次修改。
我不确定如何解释被报告的 9 次写入,但只发生了 8 次。也许一页被重复计算了。
归档时间: |
|
查看次数: |
1989 次 |
最近记录: |