Les lectures logiques sont différentes lors de l'accès aux mêmes données LOB


26

Voici trois tests simples qui lisent les mêmes données, mais rapportent des lectures logiques très différentes:

Installer

Le script suivant crée une table de test avec 100 lignes identiques, chacune contenant une colonne xml avec suffisamment de données pour garantir son stockage hors ligne. Dans ma base de données de test, la longueur du xml généré est de 20 204 octets pour chaque ligne.

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

Les tests

Les trois tests suivants lisent la colonne xml avec:

  1. Une SELECTdéclaration simple
  2. Assigner le xml à une variable
  3. Utilisation SELECT INTOpour créer une table temporaire
-- 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;

Résultats

La sortie est:

=== Plain SELECT ====
Tableau 'XMLTest'. Nombre de balayages 1, lectures logiques 3, lectures physiques 1, lectures anticipées 0,
    lob logique lit 795, lob physique lit 37, lob read-ahead lit 796.

=== Attribuer à une variable ====
Tableau 'XMLTest'. Nombre de balayages 1, lectures logiques 3, lectures physiques 1, lectures anticipées 0,
    lob logique lit 0, lob physique lit 0, lob read-ahead lit 0.

=== SELECT INTO ====
Tableau 'XMLTest'. Nombre de balayages 1, lectures logiques 3, lectures physiques 1, lectures anticipées 0,
    lob logique lit 300, lob physique lit 37, lob read-ahead lit 400.

Des questions

  • Pourquoi les lectures LOB sont-elles si différentes?
  • Certes, les mêmes données exactes ont été lues dans chaque test?

Réponses:


27

Toutes les lectures ne sont pas égales. SQL Server sait que l'accès aux données LOB coûte cher et essaie de l'éviter lorsque cela est possible. Il existe également des différences détaillées dans la façon dont les données LOB sont lues dans chaque cas:

Sommaire

Les chiffres sont différents car:

  • La sélection lit le LOB en morceaux de la taille d'un paquet
  • Le test d'affectation des variables ne lit pas du tout le LOB
  • Le test "sélectionner dans" lit le LOB dans des pages entières

Détail

  1. Plaine SELECT

    Sélectionnez le plan

    L'analyse d'index en cluster ne lit aucune donnée LOB. Il affecte uniquement une poignée LOB du moteur de stockage . Le handle n'est utilisé que lorsque le contrôle revient à la racine du plan.

    Le contenu LOB de la ligne actuelle est lu en morceaux de la taille d'un paquet TDS et diffusé en continu vers le client. Les lectures logiques comptent le nombre de fois qu'une page est touchée, donc:

    Le nombre de lectures signalées est égal au nombre de lectures fragmentées effectuées, plus un pour chaque fois qu'une transition de page LOB se produit.

    Par exemple: Une lecture logique est comptée au début de chaque bloc lorsque le processus touche la page correspondant à la position actuelle du flux. Lorsque les paquets sont plus petits qu'une page de base de données (le cas habituel), plusieurs lectures logiques sont comptées pour la même page. Si la taille du paquet était si grande que l'ensemble du LOB pouvait tenir dans un seul bloc, le nombre de lectures logiques signalées serait le nombre de pages du LOB.

  2. Affectation variable

    Plan variable

    L'indice attribue une analyse en cluster LOB poignée comme avant. À la racine du plan, le descripteur LOB est copié dans la variable. Les données LOB elles-mêmes ne sont jamais accessibles (zéro lecture LOB), car la variable n'est jamais lue. Même si c'était le cas, ce ne serait que via la dernière poignée LOB affectée.

    Il n'y a pas de lecture LOB car les données LOB ne sont jamais accessibles.

  3. SELECT INTO

    Sélectionnez dans le plan

    Ce plan utilise le fournisseur d'ensemble de lignes en bloc pour copier les données LOB de la table source vers la nouvelle table. Il traite une page LOB complète à chaque lecture (pas de streaming ou de segmentation).

    Le nombre de lectures logiques correspond au nombre de pages LOB dans la table de test.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.