同じLOBデータにアクセスする場合、論理読み取りが異なる


26

同じデータを読み取りながら、非常に異なる論理読み取りを報告する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列を次のように読み取ります。

  1. わかりやすいSELECT声明
  2. xmlを変数に割り当てる
  3. を使用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。

ご質問

  • LOBの読み取りがなぜこれほど異なるのですか?
  • 確かに各テストでまったく同じデータが読み取られましたか?

回答:


27

すべての読み取りが等しいわけではありません。SQL Serverは、LOBデータへのアクセスが高価であることを認識しており、可能な場合はそれを回避しようとします。それぞれの場合にLOBデータの読み取り方法にも詳細な違いがあります。

概要

数値は次の理由で異なります。

  • selectは、パケットサイズのチャンクで LOBを読み取ります
  • 変数割り当てテスト LOBをまったく読み取りません
  • 「select into」テストは、ページ全体で LOBを読み取ります

詳細

  1. 平野 SELECT

    プランを選択

    クラスター化インデックススキャンは、LOBデータを読み取りません。ストレージエンジンLOB ハンドルのみを割り当てます。ハンドルは、制御がプランのルートに戻るまで使用されません。

    現在の行のLOBコンテンツは、TDSパケットサイズのチャンクで読み取られ、クライアントにストリーミングされます。論理読み取りは、ページがタッチされた回数をカウントするため、次のようになります。

    報告される読み取りの数は、実行されるチャンク読み取りの数に、LOBページの移行が発生するたびに1を加えた数に等しくなります。

    たとえば、プロセスがストリームの現在の位置に対応するページに触れると、各チャンクの開始時に論理読み取りがカウントされます。パケットがデータベースページよりも小さい場合(通常の場合)、同じページに対して複数の論理読み取りがカウントされます。パケットサイズが大きすぎてLOB全体が1つのチャンクに収まる場合、報告される論理読み取りの数はLOBページの数になります。

  2. 変数の割り当て

    変動プラン

    クラスタ化インデックススキャンは、以前と同様にLOB ハンドルを割り当てます。プランのルートで、LOBハンドルが変数にコピーされます。変数は読み取られないため、LOBデータ自体はアクセスされません(LOB読み取りがゼロ)。それがあったとしても、最後に割り当てられたLOBハンドルを介してのみ行われます。

    LOBデータにはアクセスしないため、LOB読み取りはありません。

  3. SELECT INTO

    計画に選択

    このプランでは、バルク行セットプロバイダーを使用して、ソーステーブルから新しいテーブルにLOBデータをコピーします。読み取りごとに完全なLOBページを処理します(ストリーミングまたはチャンクなし)。

    論理読み取りの数は、テストテーブルのLOBページの数に対応します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.