Ответы:
STATISTICS IO
не включает чтения хранилища версий, по крайней мере, для хранилища версий в базе данных tempdb.
Вот демо для доказательства:
--setup script
USE master
GO
CREATE DATABASE TestDB
GO
ALTER DATABASE TestDB
SET ALLOW_SNAPSHOT_ISOLATION ON
GO
USE TestDB
GO
DROP TABLE IF EXISTS dbo.Test
GO
CREATE TABLE dbo.Test (ID int identity PRIMARY KEY, junk int)
INSERT dbo.Test
SELECT TOP (100000) 1
FROM master.dbo.spt_values a
CROSS JOIN master.dbo.spt_values b
Запустите цикл обновления 30-х годов на одной вкладке SSMS
--UPDATE loop
SET NOCOUNT ON
DECLARE @stop datetime = DATEADD(SECOND, 30, GETDATE())
WHILE GETDATE() < @stop
BEGIN
BEGIN TRAN
UPDATE dbo.Test
SET junk += 1
COMMIT
END
UPDATE dbo.Test
SET junk = 1
И пока идет цикл, выполните два одинаковых запроса SNAPSHOT
с STATISTICS IO ON
, разделенных 15-ю, чтобы накапливать версии.
USE TestDB
SET STATISTICS IO ON
GO
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
BEGIN TRAN
SELECT MAX(junk)
FROM dbo.Test
WAITFOR DELAY '00:00:15'
SELECT MAX(junk)
FROM dbo.Test
COMMIT
Статистика IO показывает идентичные чтения:
Но фактический план выполнения показывает, что сканирование второго запроса занимает гораздо больше времени из-за чтения хранилища версий.
Чтобы доказать себе, что этот запрос привел к чтению из базы данных tempdb, вы можете использовать этот сеанс расширенных событий (который явно лучше, чем Profiler), отфильтрованный к сеансу, где выполняются запросы на чтение:
CREATE EVENT SESSION [file_reads] ON SERVER
ADD EVENT sqlserver.file_read_completed(
ACTION(sqlserver.session_id,sqlserver.sql_text)
WHERE ([sqlserver].[session_id]=(52)))
ADD TARGET package0.event_file(SET filename=N'file_reads')
GO
Просматривая «живые данные» для этого сеанса XE во время демонстрации, вы можете увидеть чтения по базе данных с идентификатором 2 (tempdb), и она также фиксирует текст нашего запроса на чтение:
Особая благодарность Полу Уайту за то, что он поднял эту проблему с STATISTICS IO.