同じデータを読み取るが、非常に異なる論理読み取りを報告する3つの簡単なテストを次に示します。
次のスクリプトは、100個の同一行を持つテストテーブルを作成します。各行には、行から格納されることを保証するのに十分なデータを持つxml列が含まれます。私のテストデータベースでは、生成されるxmlの長さは各行で20,204バイトです。
-- Conditional drop
IF OBJECT_ID(N'dbo.XMLTest', N'U') IS NOT NULL
DROP TABLE dbo.XMLTest;
GO
-- Create test table
CREATE TABLE dbo.XMLTest
(
ID integer IDENTITY PRIMARY KEY,
X xml NULL
);
GO
-- Add 100 wide xml rows
DECLARE @X xml;
SET @X =
(
SELECT TOP (100) *
FROM sys.columns AS C
FOR XML
PATH ('row'),
ROOT ('root'),
TYPE
);
INSERT dbo.XMLTest
(X)
SELECT TOP (100)
@X
FROM sys.columns AS C;
-- Flush dirty buffers
CHECKPOINT;
次の3つのテストでは、xml列を読み取ります。
SELECT
ステートメントSELECT INTO
を使用して一時テーブルを作成する-- No row count messages or graphical plan
-- Show I/O statistics
SET NOCOUNT ON;
SET STATISTICS XML OFF;
SET STATISTICS IO ON;
GO
PRINT CHAR(10) + '=== Plain SELECT ===='
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SELECT XT.X
FROM dbo.XMLTest AS XT;
GO
PRINT CHAR(10) + '=== Assign to a variable ===='
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
DECLARE @X xml;
SELECT
@X = XT.X
FROM dbo.XMLTest AS XT;
GO
PRINT CHAR(10) + '=== SELECT INTO ===='
IF OBJECT_ID(N'tempdb..#T', N'U') IS NOT NULL
DROP TABLE #T;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SELECT
XT.X
INTO #T
FROM dbo.XMLTest AS XT
GO
SET STATISTICS IO OFF;
出力は次のとおりです。
===プレーンSELECT ==== テーブル 'XMLTest'。スキャンカウント1、論理読み取り3、物理読み取り1、先読み読み取り0、 lob論理読み取り795、lob物理読み取り37、lob先読み読み取り796。 ===変数に割り当てます==== テーブル 'XMLTest'。スキャンカウント1、論理読み取り3、物理読み取り1、先読み読み取り0、 lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0。 === SELECT INTO ==== 表「XMLTest」。スキャンカウント1、論理読み取り3、物理読み取り1、先読み読み取り0、 lob論理読み取り300、lob物理読み取り37、lob先読み読み取り400。
すべての読み取りが等しいわけではありません。 SQL Serverは、LOBデータへのアクセスは負荷が高いことを認識しており、可能な場合は回避しようとします。また、それぞれの場合のLOBデータの読み取り方法にも詳細な違いがあります。
数が異なる理由は次のとおりです。
プレーンSELECT
クラスタ化インデックススキャンは、LOBデータを読み取りません。ストレージエンジンLOBhandleのみを割り当てます。ハンドルは、制御がプランのルートに戻るまで使用されません。
現在の行のLOBコンテンツはTDSパケットサイズのチャンクで読み取られ、クライアントにストリーミングされます。論理読み取りは、ページがタッチされた回数をカウントするため、次のようになります。
報告された読み取りの数は、実行されたチャンクされた読み取りの数に、LOBページの遷移が発生するたびに1を加えた数に等しくなります。
次に例を示します。プロセスがストリームの現在の位置に対応するページにアクセスすると、各チャンクの開始時に論理読み取りがカウントされます。パケットがデータベースページよりも小さい場合(通常の場合)、同じページに対して複数の論理読み取りがカウントされます。パケットサイズが大きすぎてLOB全体が1つのチャンクに収まる場合、報告される論理読み取りの数はLOBページの数になります。
変数の割り当て
クラスタ化インデックススキャンは、以前と同様にLOBhandleを割り当てます。プランのルートで、LOBハンドルが変数にコピーされます。変数は決して読み取られないため、LOBデータ自体にアクセスされることはありません(LOB読み取りはゼロ)。たとえそうであっても、最後に割り当てられたLOBハンドルを介してのみ行われます。
LOBデータはアクセスされないため、LOBの読み取りはありません。
SELECT INTO
このプランは、一括行セットプロバイダーを使用して、LOBデータをソーステーブルから新しいテーブルにコピーします。読み取りごとに完全なLOBページを処理します(ストリーミングやチャンキングはありません)。
論理読み取りの数は、テストテーブルのLOBページの数に対応します。