Pembacaan logis berbeda ketika mengakses data LOB yang sama

26

Berikut adalah tiga tes sederhana yang membaca data yang sama, namun melaporkan pembacaan logis yang sangat berbeda:

Mendirikan

Script berikut membuat tabel pengujian dengan 100 baris identik, masing-masing berisi kolom xml dengan data yang cukup untuk memastikannya disimpan di luar baris. Dalam database pengujian saya, panjang xml yang dihasilkan adalah 20.204 byte untuk setiap baris.

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

Tes

Tiga tes berikut membaca kolom xml dengan:

  1. SELECTPernyataan sederhana
  2. Menetapkan xml ke variabel
  3. Menggunakan SELECT INTOuntuk membuat tabel sementara
-- 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;

Hasil

Outputnya adalah:

=== PILIH Biasa ====
Tabel 'XMLTest'. Pindai hitungan 1, bacaan logis 3, bacaan fisik 1, baca-depan dibaca 0,
    lob logis membaca 795, lob fisik membaca 37, lob baca-depan membaca 796.

=== Tetapkan ke variabel ====
Tabel 'XMLTest'. Pindai hitungan 1, bacaan logis 3, bacaan fisik 1, baca-depan dibaca 0,
    lob logis membaca 0, lob fisik membaca 0, lob baca-depan membaca 0.

=== PILIH KE ====
Tabel 'XMLTest'. Pindai hitungan 1, bacaan logis 3, bacaan fisik 1, baca-depan dibaca 0,
    Lob membaca logis 300, lob fisik membaca 37, lob membaca-depan membaca 400.

Pertanyaan

  • Mengapa LOB berbunyi sangat berbeda?
  • Tentunya data yang sama persis dibaca di setiap tes?
Paul White mengatakan GoFundMonica
sumber

Jawaban:

27

Tidak semua bacaan sama. SQL Server tahu bahwa mengakses data LOB itu mahal, dan mencoba menghindarinya jika memungkinkan. Ada juga perbedaan terperinci dalam cara data LOB dibaca dalam setiap kasus:

Ringkasan

Jumlahnya berbeda karena:

  • Pilih membaca LOB dalam potongan seukuran paket
  • Tes penugasan variabel tidak membaca LOB sama sekali
  • Tes "select into" membaca LOB di seluruh halaman

Detail

  1. Polos SELECT

    Pilih paket

    Pemindaian Indeks Clustered tidak membaca data LOB. Ini hanya menetapkan pegangan mesin penyimpanan LOB . Pegangan tidak digunakan sampai kontrol kembali ke akar paket.

    Konten LOB baris saat ini dibaca dalam potongan berukuran paket TDS dan dialirkan ke klien. Pembacaan logis menghitung berapa kali halaman disentuh, jadi:

    Jumlah pembacaan yang dilaporkan sama dengan jumlah pembacaan yang dilakukan, ditambah satu untuk setiap kali transisi halaman LOB terjadi.

    Sebagai contoh: Pembacaan logis dihitung pada awal setiap potongan saat proses menyentuh halaman yang sesuai dengan posisi saat ini dari aliran. Ketika paket lebih kecil dari halaman basis data (kasus biasa), beberapa pembacaan logis dihitung untuk halaman yang sama. Jika ukuran paket begitu besar sehingga seluruh LOB bisa muat dalam satu potongan, jumlah pembacaan logis yang dilaporkan adalah jumlah halaman LOB.

  2. Tugas variabel

    Paket variabel

    Pemindaian Indeks Clustered menetapkan pegangan LOB seperti sebelumnya. Pada akar rencana, pegangan LOB disalin ke variabel. Data LOB itu sendiri tidak pernah diakses (nol LOB dibaca), karena variabel tidak pernah dibaca. Bahkan jika itu, itu hanya akan melalui pegangan LOB yang ditugaskan terakhir.

    Tidak ada LOB yang dibaca karena data LOB tidak pernah diakses.

  3. SELECT INTO

    Pilih Rencana Ke

    Paket ini menggunakan penyedia rowset massal untuk menyalin data LOB dari tabel sumber ke tabel baru. Itu memproses halaman LOB lengkap pada setiap membaca (tidak ada streaming atau chunking)

    Jumlah pembacaan logis sesuai dengan jumlah halaman LOB dalam tabel pengujian.

Paul White mengatakan GoFundMonica
sumber