SQL Serverがクラスター化インデックスのデータにアクセスする方法を理解しようとしています。私の理解では、テーブルにクラスター化インデックスがある場合、SQLは、シーク述語を使用してレコードを保持する単一のページにシークできるはずです。
ただし、クエリを実行するとテストが表示され、さらに数ページのデータページが読み込まれます。
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
SQLが緑色でマークされたすべてのページをロードするのはなぜですか?ページはREAD AHEADによってロードされていますか?
これは 先読みとしてカウントされない先読み で説明されています
この投稿で話したかったのは、SQLがEnterpriseと見なされるエディション(つまり、Developer、Evaluation、およびEnterprise自体)を実行しているときに、クエリによってトリガーできる別のプリフェッチメカニズムでした。この最適化の目的は、キャッシュをできるだけ早くウォームアップすることです。 そのために、バッファープールは、ディスクから単一のページを読み取る要求を、最初に要求されたページを含むエクステント全体を読み取る要求に変換します。
あなたの場合、DBCC DROPCLEANBUFFERS
でバッファキャッシュをクリアした後にこれを実行しました。したがって、SQL Serverは、キャッシュをすばやくウォームアップしようとする状態にあります。
シークを実行するには、3ページを読み取る必要がありました(インデックスの各レベルに1つ)。これらは、ページ1111
、1382
、および1061
でした。
つまり、ページ番号1056 - 1063
、1104 - 1111
、1376 - 1383
の3つのエクステント全体を取り込むことになりました。
見積もりに記載されていない他のSKUに対して同じ実験を行った場合(トレースフラグ840が有効になっていない場合)、予想される3つのページが表示されます(以下はExpress LocalDBに対するものです)。