Letture logiche diverse quando si accede agli stessi dati LOB


26

Ecco tre semplici test che leggono gli stessi dati, ma riportano letture logiche molto diverse:

Impostare

Lo script seguente crea una tabella di test con 100 righe identiche, ognuna contenente una colonna xml con dati sufficienti per garantire che sia archiviata fuori dalla riga. Nel mio database di test, la lunghezza dell'xml generato è di 20.204 byte per ogni riga.

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

test

I seguenti tre test leggono la colonna xml con:

  1. Una semplice SELECTdichiarazione
  2. Assegnare l' xml a una variabile
  3. Utilizzo SELECT INTOper creare una tabella temporanea
-- 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;

risultati

L'output è:

=== Plain SELECT ====
Tabella 'XMLTest'. Conteggio scansioni 1, letture logiche 3, letture fisiche 1, letture anticipate 0,
    lob logico legge 795, lob fisico legge 37, lob read-ahead legge 796.

=== Assegna a una variabile ====
Tabella 'XMLTest'. Conteggio scansioni 1, letture logiche 3, letture fisiche 1, letture anticipate 0,
    lob logico legge 0, lob fisico legge 0, lob read-ahead legge 0.

=== SELEZIONA IN ====
Tabella 'XMLTest'. Conteggio scansioni 1, letture logiche 3, letture fisiche 1, letture anticipate 0,
    lob logico legge 300, lob fisico legge 37, lob read-ahead legge 400.

Domande

  • Perché le letture LOB sono così diverse?
  • Sicuramente gli stessi dati sono stati letti in ogni test?

Risposte:


27

Non tutte le letture sono uguali. SQL Server sa che l'accesso ai dati LOB è costoso e cerca di evitarlo quando possibile. Esistono inoltre differenze dettagliate nel modo in cui i dati LOB vengono letti in ciascun caso:

Sommario

I numeri sono diversi perché:

  • La selezione legge il LOB in blocchi di dimensioni di pacchetto
  • Il test di assegnazione delle variabili non legge affatto il LOB
  • Il test "seleziona in" legge il LOB in intere pagine

Dettaglio

  1. pianura SELECT

    Seleziona il piano

    Clustered Index Scan non legge alcun dato LOB. Assegna solo un handle LOB del motore di archiviazione . L'handle non viene utilizzato fino a quando il controllo non ritorna alla radice del piano.

    Il contenuto LOB della riga corrente viene letto in blocchi di dimensioni di pacchetto TDS e trasmesso in streaming al client. Le letture logiche contano il numero di volte in cui una pagina viene toccata, quindi:

    Il numero di letture riportate è uguale al numero di letture a blocchi eseguite, più una per ogni volta che si verifica una transizione di pagina LOB.

    Ad esempio: una lettura logica viene conteggiata all'inizio di ogni blocco quando il processo tocca la pagina corrispondente alla posizione corrente dello stream. Laddove i pacchetti sono più piccoli di una pagina del database (il solito caso), vengono contate diverse letture logiche per la stessa pagina. Se la dimensione del pacchetto fosse così grande che l'intero LOB potesse rientrare in un blocco, il numero di letture logiche riportate sarebbe il numero di pagine LOB.

  2. Assegnazione variabile

    Piano variabile

    Clustered Index Scan assegna un handle LOB come prima. Alla radice del piano, l'handle LOB viene copiato nella variabile. Non si accede mai ai dati LOB stessi (zero letture LOB), poiché la variabile non viene mai letta. Anche se lo fosse, sarebbe solo tramite l'ultimo handle LOB assegnato.

    Non ci sono letture LOB perché i dati LOB non sono mai accessibili.

  3. SELECT INTO

    Seleziona Nel piano

    Questo piano utilizza il provider di set di righe bulk per copiare i dati LOB dalla tabella di origine alla nuova tabella. Elabora una pagina LOB completa su ogni lettura (nessun flusso o blocco).

    Il numero di letture logiche corrisponde al numero di pagine LOB nella tabella di test.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.