Lecturas lógicas diferentes al acceder a los mismos datos LOB


26

Aquí hay tres pruebas simples que leen los mismos datos, pero informan lecturas lógicas muy diferentes:

Preparar

El siguiente script crea una tabla de prueba con 100 filas idénticas, cada una de las cuales contiene una columna xml con datos suficientes para garantizar que se almacene fuera de la fila. En mi base de datos de prueba, la longitud del xml generado es de 20,204 bytes por cada fila.

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

Pruebas

Las siguientes tres pruebas leen la columna xml con:

  1. Una SELECTdeclaración simple
  2. Asignando el xml a una variable
  3. Utilizando SELECT INTOpara crear una tabla temporal
-- 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;

Resultados

El resultado es:

=== SELECCIONAR llano ====
Tabla 'XMLTest'. Cuenta de escaneo 1, lecturas lógicas 3, lecturas físicas 1, lecturas anticipadas 0,
    las lecturas lógicas lob 795, las lecturas físicas lob 37, las lecturas anticipadas lob 796.

=== Asignar a una variable ====
Tabla 'XMLTest'. Cuenta de escaneo 1, lecturas lógicas 3, lecturas físicas 1, lecturas anticipadas 0,
    lecturas lógicas lob 0, lecturas físicas lob 0, lecturas anticipadas lob 0.

=== SELECCIONAR EN ====
Tabla 'XMLTest'. Cuenta de escaneo 1, lecturas lógicas 3, lecturas físicas 1, lecturas anticipadas 0,
    lecturas lógicas lob 300, lecturas físicas lob 37, lecturas anticipadas lob 400.

Preguntas

  • ¿Por qué las lecturas de LOB son tan diferentes?
  • ¿Seguramente se leyeron exactamente los mismos datos en cada prueba?

Respuestas:


27

No todas las lecturas son iguales. SQL Server sabe que acceder a los datos de LOB es costoso e intenta evitarlo cuando es posible. También hay diferencias detalladas en la forma en que se leen los datos LOB en cada caso:

Resumen

Los números son diferentes porque:

  • La selección lee el LOB en fragmentos de tamaño de paquete
  • La prueba de asignación de variables no lee el LOB en absoluto
  • La prueba "seleccionar en" lee el LOB en páginas enteras

Detalle

  1. Llanura SELECT

    Seleccionar plan

    La exploración de índice agrupado no lee ningún dato de LOB. Solo asigna una manija LOB del motor de almacenamiento . El identificador no se usa hasta que el control vuelve a la raíz del plan.

    El contenido de LOB de la fila actual se lee en fragmentos de tamaño de paquete TDS y se transmite al cliente. Las lecturas lógicas cuentan el número de veces que se toca una página, por lo que:

    El número de lecturas informadas es igual al número de lecturas fragmentadas realizadas, más una por cada vez que se produce una transición de página LOB.

    Por ejemplo: una lectura lógica se cuenta al comienzo de cada fragmento cuando el proceso toca la página correspondiente a la posición actual de la secuencia. Cuando los paquetes son más pequeños que una página de base de datos (el caso habitual), se cuentan varias lecturas lógicas para la misma página. Si el tamaño del paquete fuera tan grande que todo el LOB pudiera caber en un fragmento, el número de lecturas lógicas informadas sería el número de páginas de LOB.

  2. Asignación variable

    Plan variable

    La exploración de índice agrupado asigna un identificador de LOB como antes. En la raíz del plan, el identificador LOB se copia a la variable. Nunca se accede a los datos LOB en sí (cero lecturas LOB), porque la variable nunca se lee. Incluso si lo fuera, solo sería a través del último LOB asignado.

    No hay lecturas de LOB porque nunca se accede a los datos de LOB.

  3. SELECT INTO

    Seleccionar en el plan

    Este plan utiliza el proveedor de conjuntos de filas masivos para copiar los datos de LOB de la tabla de origen a la nueva tabla. Procesa una página LOB completa en cada lectura (sin transmisión ni fragmentación).

    El número de lecturas lógicas corresponde al número de páginas LOB en la tabla de prueba.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.