Logische Lesevorgänge unterscheiden sich beim Zugriff auf dieselben LOB-Daten

26

Hier sind drei einfache Tests, die dieselben Daten lesen, jedoch sehr unterschiedliche logische Lesevorgänge melden:

Installieren

Das folgende Skript erstellt eine Testtabelle mit 100 identischen Zeilen, von denen jede eine XML- Spalte mit genügend Daten enthält, um sicherzustellen, dass sie außerhalb der Zeile gespeichert werden. In meiner Test - Datenbank, die Länge des xml erzeugte 20.204 Bytes für jede Zeile.

-- 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;

Tests

Die folgenden drei Tests lesen die XML- Spalte mit:

  1. Eine klare SELECTAussage
  2. Zuweisen der XML zu einer Variablen
  3. Verwenden Sie SELECT INTO, um eine temporäre Tabelle zu erstellen
-- 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;

Ergebnisse

Die Ausgabe ist:

=== Plain SELECT ====
Tabelle 'XMLTest'. Scananzahl 1, logische Lesevorgänge 3, physische Lesevorgänge 1, Vorauslesevorgänge 0,
    logische Lesevorgänge 795, physikalische Lesevorgänge 37, Vorauslesevorgänge 796.

=== Einer Variablen zuweisen ====
Tabelle 'XMLTest'. Scananzahl 1, logische Lesevorgänge 3, physische Lesevorgänge 1, Vorauslesevorgänge 0,
    lob logische Lesevorgänge 0, lob physikalische Lesevorgänge 0, lob Vorauslesevorgänge 0.

=== SELECT INTO ====
Tabelle 'XMLTest'. Scananzahl 1, logische Lesevorgänge 3, physische Lesevorgänge 1, Vorauslesevorgänge 0,
    logische Lesevorgänge 300, physikalische Lesevorgänge 37, Vorauslesevorgänge 400.

Fragen

  • Warum liest sich das LOB so anders?
  • Sicherlich wurden bei jedem Test genau die gleichen Daten gelesen?
Paul White sagt GoFundMonica
quelle

Antworten:

27

Nicht alle Lesevorgänge sind gleich. SQL Server weiß, dass der Zugriff auf LOB-Daten teuer ist, und versucht, sie nach Möglichkeit zu vermeiden. Es gibt auch detaillierte Unterschiede in der Art und Weise, wie die LOB-Daten jeweils gelesen werden:

Zusammenfassung

Die Zahlen sind unterschiedlich, weil:

  • Die Auswahl liest das LOB in Paketen
  • Der Variablenzuweisungstest liest das LOB überhaupt nicht
  • Der "Auswählen in" -Test liest das LOB in ganzen Seiten

Detail

  1. Einfach SELECT

    Plan auswählen

    Der Clustered Index Scan liest keine LOB-Daten. Es wird nur ein Speicher-Engine-LOB- Handle zugewiesen . Das Handle wird erst verwendet, wenn die Steuerung zum Stamm des Plans zurückkehrt.

    Der LOB-Inhalt der aktuellen Zeile wird in TDS-Paketen gelesen und an den Client gestreamt. Logische Lesevorgänge zählen, wie oft eine Seite berührt wurde.

    Die Anzahl der gemeldeten Lesevorgänge entspricht der Anzahl der geteilten Lesevorgänge plus eins bei jedem LOB-Seitenübergang.

    Beispiel: Ein logischer Lesevorgang wird am Anfang jedes Blocks gezählt, wenn der Prozess die Seite berührt, die der aktuellen Position des Streams entspricht. Wo Pakete kleiner als eine Datenbankseite sind (der übliche Fall), werden mehrere logische Lesevorgänge für dieselbe Seite gezählt. Wenn die Paketgröße so groß wäre, dass das gesamte LOB in einen Block passen könnte, wäre die Anzahl der gemeldeten logischen Lesevorgänge die Anzahl der LOB-Seiten.

  2. Variablenzuordnung

    Variabler Plan

    Der Clustered Index Scan weist wie zuvor ein LOB- Handle zu. Im Stamm des Plans wird das LOB-Handle in die Variable kopiert. Auf die LOB-Daten selbst wird niemals zugegriffen (Null-LOB-Lesevorgänge), da die Variable niemals gelesen wird. Selbst wenn dies der Fall wäre, würde dies nur über das zuletzt zugewiesene LOB-Handle erfolgen.

    Es gibt keine LOB-Lesevorgänge, da niemals auf die LOB-Daten zugegriffen wird.

  3. SELECT INTO

    Wählen Sie In Plan

    Dieser Plan verwendet den Massen-Rowset-Provider, um die LOB-Daten aus der Quellentabelle in die neue Tabelle zu kopieren. Bei jedem Lesevorgang wird eine vollständige LOB-Seite verarbeitet (kein Streaming oder Chunking).

    Die Anzahl der logischen Lesevorgänge entspricht der Anzahl der LOB-Seiten in der Testtabelle.

Paul White sagt GoFundMonica
quelle