我试图了解 SQL Server 如何从聚集索引访问数据。我的理解是,当表有聚集索引时,SQL 应该能够使用 seek 谓词搜索保存记录的单个页面。
但是,当执行查询时,我的测试显示它会加载更多数据页。
设置
CREATE TABLE t2(id INT IDENTITY PRIMARY KEY CLUSTERED,col2 VARCHAR(500),col3 VARCHAR(500));
INSERT INTO [dbo].[t2]([col2],[col3])
SELECT TOP 10010 REPLICATE('z',490),REPLICATE('*',490)
FROM sys.all_columns c1,
sys.all_columns c2
以下查询
select *
from sys.dm_db_index_physical_stats(db_id(),object_id(N'dbo.t2'),DEFAULT,null,'DETAILED');
将输出显示为
然后我清除了缓存
CHECKPOINT
GO
DBCC DROPCLEANBUFFERS
SELECT
并在一行中运行以下搜索
SELECT [fplc].*,[t2].[col3] FROM [dbo].[t2] AS [t2]
CROSS APPLY sys.[fn_PhysLocCracker](%%physloc%%) AS [fplc]
WHERE id=4582
上面的查询告诉我记录位于页面 1061
我使用下面的代码检查已将多少页加载到缓冲区中以获取我的 SELECT 的结果
SELECT buffers.* FROM sys.dm_os_buffer_descriptors buffers
INNER JOIN sys.allocation_units AS au
ON au.[allocation_unit_id] = buffers.[allocation_unit_id]
INNER JOIN sys.partitions AS p
ON au.[container_id] = p.[partition_id]
INNER JOIN sys.indexes AS i
ON i.[index_id] = p.[index_id] AND p.[object_id] = i.[object_id]
WHERE p.[object_id] > 100
and [database_id] = DB_ID () AND i.[object_id]=OBJECT_ID('t2')
ORDER BY [page_level] desc
这在预读中进行了解释,这不算作预读
在您的情况下,您在使用
DBCC DROPCLEANBUFFERS
. 因此 SQL Server 处于尝试快速预热缓存的状态。您需要阅读三页来执行查找(索引的每一级都有一个)。这些是页
1111
和。1382
1061
因此,您最终引入了三个带有页码
1056 - 1063
和.1104 - 1111
1376 - 1383
如果您对报价中提到的其他 SKU 进行相同的实验(并且未启用 traceflag 840),您应该会看到预期的三个页面(以下是针对 Express LocalDB)