ตรรกะอ่านแตกต่างกันเมื่อเข้าถึงข้อมูล LOB เดียวกัน


26

นี่คือการทดสอบสามแบบที่อ่านข้อมูลเดียวกัน แต่รายงานการอ่านเชิงตรรกะที่แตกต่างกันมาก:

ติดตั้ง

สคริปต์ต่อไปนี้สร้างตารางทดสอบที่มี 100 แถวเหมือนกันแต่ละแถวมีคอลัมน์xml ที่มีข้อมูลเพียงพอเพื่อให้แน่ใจว่าจะถูกเก็บไว้นอกแถว ในฐานข้อมูลการทดสอบของฉันความยาวของxml ที่สร้างขึ้นคือ 20,204 ไบต์สำหรับแต่ละแถว

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

การทดสอบ

การทดสอบสามแบบต่อไปนี้อ่านคอลัมน์xmlด้วย:

  1. ธรรมดาSELECTคำสั่ง
  2. การกำหนดxmlให้กับตัวแปร
  3. ใช้SELECT INTOเพื่อสร้างตารางชั่วคราว
-- 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;

ผล

ผลลัพธ์คือ:

=== เลือกแบบธรรมดา ====
ตาราง 'XMLTest' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 3, การอ่านทางกายภาพ 1, การอ่านล่วงหน้าอ่าน 0,
    โลจิคัล lob อ่าน 795, lob ฟิสิคัลอ่าน 37, lob read-ahead อ่าน 796

=== กำหนดให้กับตัวแปร ====
ตาราง 'XMLTest' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 3, การอ่านทางกายภาพ 1, การอ่านล่วงหน้าอ่าน 0,
    โลจิคัล lob อ่าน 0, lob ฟิสิคัลอ่านเป็น 0, lob read-ahead อ่าน 0

=== เลือกเข้าสู่ ====
ตาราง 'XMLTest' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 3, การอ่านทางกายภาพ 1, การอ่านล่วงหน้าอ่าน 0,
    lob ลอจิกอ่าน 300, ลูกเทนนิสกายภาพอ่าน 37, lob read-ahead อ่าน 400

คำถาม

  • เหตุใด LOB จึงอ่านแตกต่างกันมาก
  • แน่นอนข้อมูลเดียวกันที่ถูกอ่านในการทดสอบแต่ละครั้ง?

คำตอบ:


27

การอ่านทั้งหมดไม่เท่ากัน SQL Server รู้ว่าการเข้าถึงข้อมูล LOB มีราคาแพงและพยายามหลีกเลี่ยงเมื่อเป็นไปได้ นอกจากนี้ยังมีความแตกต่างอย่างละเอียดในวิธีการอ่านข้อมูล LOB ในแต่ละกรณี:

สรุป

ตัวเลขต่างกันเพราะ:

  • เลือกอ่านลอบในแพ็คเก็ตขนาดชิ้น
  • การทดสอบการกำหนดตัวแปรไม่อ่าน LOB เลย
  • การทดสอบ "เลือกเข้าสู่" จะอ่าน LOB ทั้งหน้า

รายละเอียด

  1. ธรรมดา SELECT

    เลือกแผน

    การสแกนดัชนีแบบคลัสเตอร์ไม่อ่านข้อมูล LOB ใด ๆ เพียงกำหนดเครื่องมือจัดการ LOB ที่จับเท่านั้น หมายเลขอ้างอิงจะไม่ถูกใช้จนกว่าการควบคุมจะกลับไปที่รูทของแผน

    เนื้อหา LOB ของแถวปัจจุบันถูกอ่านในชุดขนาดแพ็คเก็ต TDS และสตรีมไปยังไคลเอ็นต์ การอ่านเชิงตรรกะนับจำนวนครั้งที่มีการแตะหน้าดังนั้น:

    จำนวนการอ่านที่รายงานเท่ากับจำนวนการอ่านที่อ่านแล้วที่ดำเนินการรวมหนึ่งครั้งสำหรับการเปลี่ยนหน้า LOB

    ตัวอย่างเช่น: การอ่านแบบลอจิคัลจะถูกนับที่จุดเริ่มต้นของแต่ละชิ้นในขณะที่กระบวนการสัมผัสหน้าเว็บที่สอดคล้องกับตำแหน่งปัจจุบันของกระแส ในกรณีที่แพ็คเก็ตมีขนาดเล็กกว่าหน้าฐานข้อมูล (กรณีปกติ) การอ่านเชิงตรรกะหลายครั้งจะถูกนับสำหรับหน้าเดียวกัน หากขนาดแพ็คเก็ตมีขนาดใหญ่จน LOB ทั้งหมดสามารถใส่ได้ในหนึ่งก้อนจำนวนการอ่านโลจิคัลที่รายงานจะเป็นจำนวนหน้า LOB

  2. การมอบหมายตัวแปร

    แผนแปรปรวน

    การสแกนดัชนีแบบคลัสเตอร์จะกำหนดหมายเลขอ้างอิง LOB ให้เหมือนเมื่อก่อน ที่รากของแผนหมายเลขอ้างอิง LOB จะถูกคัดลอกไปยังตัวแปร ข้อมูล LOB จะไม่ถูกเข้าถึง (อ่าน LOB เป็นศูนย์) เนื่องจากตัวแปรไม่เคยอ่าน แม้ว่ามันจะเป็นผ่านทางหมายเลขอ้างอิงลอบที่ได้รับมอบหมายล่าสุด

    ไม่มีการอ่าน LOB เนื่องจากไม่มีการเข้าถึงข้อมูล LOB

  3. SELECT INTO

    เลือกเป็นแผน

    แผนนี้ใช้ตัวให้บริการ rowset จำนวนมากเพื่อคัดลอกข้อมูล LOB จากตารางต้นฉบับไปยังตารางใหม่ มันประมวลผลหน้า LOB ที่สมบูรณ์ในการอ่านแต่ละครั้ง (ไม่มีการสตรีมหรือการแยกชิ้น)

    จำนวนการอ่านแบบลอจิคัลสอดคล้องกับจำนวนหน้า LOB ในตารางทดสอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.