ตรรกะอ่านบนโต๊ะ temp ทั่วโลก แต่ไม่ได้อยู่ในตาราง temp ระดับเซสชั่น


11

พิจารณา MCVE แบบง่าย ๆ ต่อไปนี้:

SET STATISTICS IO, TIME OFF;
USE tempdb;

IF OBJECT_ID(N'tempdb..#t1', N'U') IS NOT NULL DROP TABLE #t1;
CREATE TABLE #t1
(
    r int NOT NULL
);

IF OBJECT_ID(N'tempdb..##t1', N'U') IS NOT NULL DROP TABLE ##t1;
CREATE TABLE ##t1
(
    r int NOT NULL
);

IF OBJECT_ID(N'dbo.s1', N'U') IS NOT NULL DROP TABLE dbo.s1;
CREATE TABLE dbo.s1 
(
    r int NOT NULL
        PRIMARY KEY CLUSTERED
);

INSERT INTO dbo.s1 (r)
SELECT TOP(10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM sys.syscolumns sc1
    CROSS JOIN sys.syscolumns sc2;
GO

เมื่อฉันรันการแทรกต่อไปนี้การแทรกเข้าไป#t1จะไม่แสดงสถิติ I / O สำหรับตารางชั่วคราว อย่างไรก็ตามการแทรกเข้าไป##t1 จะแสดงสถิติ I / O สำหรับตารางอุณหภูมิ

SET STATISTICS IO, TIME ON;
GO

INSERT INTO #t1 (r)
SELECT r
FROM dbo.s1;

สถิติเอาท์พุท:

SQL Server แยกวิเคราะห์และรวบรวมเวลา: 
   เวลา CPU = 0 ms, เวลาที่ผ่านไป = 1 ms
ตาราง 's1' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 19, การอ่านทางกายภาพ 0, การอ่านล่วงหน้าอ่าน 0, lob ตรรกะอ่าน 0, lob การอ่านทางกายภาพ 0, lob การอ่านล่วงหน้าอ่าน 0

 เวลาดำเนินการของ SQL Server:
   เวลา CPU = 16 ms, เวลาที่ผ่านไป = 9 ms

(ได้รับผลกระทบ 10,000 แถว)
INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;
SQL Server แยกวิเคราะห์และรวบรวมเวลา: 
   เวลา CPU = 0 ms, เวลาที่ผ่านไป = 1 ms
ตาราง '## t1' จำนวนการสแกน 0, อ่านโลจิคัล 10016, อ่านฟิสิคัล 0, อ่านล่วงหน้าอ่าน 0, โลปลอจิกอ่าน 0, lob ฟิสิคัลอ่าน 0, lob อ่านล่วงหน้าอ่าน 0
ตาราง 's1' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 19, การอ่านทางกายภาพ 0, การอ่านล่วงหน้าอ่าน 0, lob ตรรกะอ่าน 0, lob การอ่านทางกายภาพ 0, lob การอ่านล่วงหน้าอ่าน 0

 เวลาดำเนินการของ SQL Server:
   เวลา CPU = 47 ms, เวลาที่ผ่านไป = 45 ms

(ได้รับผลกระทบ 10,000 แถว)

เหตุใดจึงมีการอ่านจำนวนมากบนตาราง ## temp เมื่อฉันใส่เท่านั้น?

คำตอบ:


11

ไม่ได้ใช้การบันทึกขั้นต่ำเมื่อใช้INSERT INTOและตารางชั่วคราวทั่วโลก

การแทรกหนึ่งล้านแถวในตารางชั่วคราวทั่วโลกโดยใช้ INSERT INTO

INSERT INTO ##t1 (r)
SELECT top(1000000) s1.r
FROM dbo.s1
CROSS APPLY  dbo.s1 S2;

เมื่อทำงานSELECT * FROM fn_dblog(NULL, NULL)ในขณะที่แบบสอบถามข้างต้นกำลังดำเนินการจะส่งกลับแถว ~ 1M

ป้อนคำอธิบายรูปภาพที่นี่

LOP_INSERT_ROWการดำเนินการหนึ่งสำหรับแต่ละแถว + ข้อมูลบันทึกอื่น ๆ


การแทรกแบบเดียวกันบนตารางชั่วคราว

INSERT INTO #t1 (r)
SELECT top(1000000) s1.r
FROM dbo.s1
CROSS APPLY  dbo.s1 S2;

ส่งคืนได้มากถึง 700 แถวเท่านั้น SELECT * FROM fn_dblog(NULL, NULL)

ป้อนคำอธิบายรูปภาพที่นี่

บันทึกน้อยที่สุด


การแทรกหนึ่งล้านแถวในตารางชั่วคราวทั่วโลกโดยใช้ SELECT INTO

SELECT top(1000000) s1.r
INTO ##t2
FROM dbo.s1
CROSS APPLY  dbo.s1 S2;

ป้อนคำอธิบายรูปภาพที่นี่

SELECT INTO ตารางชั่วคราวที่มีระเบียน 10k

SELECT s1.r
INTO ##t2
FROM dbo.s1;

สถิติเวลาและ IO

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 16 ms,  elapsed time = 10 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

จากบล็อกนี้เราสามารถเพิ่มTABLOCKเพื่อเริ่มการบันทึกขั้นต่ำบนตารางฮีพ

INSERT INTO ##t1 WITH(TABLOCK) (r)
SELECT   s1.r
FROM dbo.s1

ตรรกะอ่านต่ำ

Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(10000 rows affected)

ส่วนหนึ่งของคำตอบโดย @PaulWhite เกี่ยวกับวิธีการบรรลุการเข้าสู่ระบบน้อยที่สุดในตารางชั่วคราว

ไม่ตารางชั่วคราวในเครื่อง (#temp) เป็นแบบส่วนบุคคลในการสร้างเซสชันดังนั้นจึงไม่จำเป็นต้องมีคำใบ้ในการล็อคตาราง จำเป็นต้องมีคำแนะนำในการล็อคตารางสำหรับตารางชั่วคราวทั่วโลก (## temp) หรือตารางปกติ (dbo.temp) ที่สร้างใน tempdb เนื่องจากสามารถเข้าถึงได้จากหลายเซสชัน

สร้างตารางปกติเพื่อทดสอบสิ่งนี้:

CREATE TABLE dbo.bla
(
    r int NOT NULL 
);

เติมด้วย 1M บันทึก

INSERT INTO bla 
SELECT   top(1000000)s1.r
FROM dbo.s1
CROSS APPLY  dbo.s1 S2;

> 1 ลอจิกอ่านในตารางนี้

Table 's1'. Scan count 17, logical reads 155, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'bla'. Scan count 0, logical reads 1001607, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

คำตอบของ Paul White อธิบายการอ่านเชิงตรรกะที่รายงานบนโต๊ะอุณหภูมิโลก

โดยทั่วไปแล้วการอ่านแบบลอจิคัลจะถูกรายงานสำหรับตารางเป้าหมายเมื่อไม่มีการบันทึกการแทรก

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


ข้อสรุป

ข้อสรุปINSERT INTOคือการที่ไม่สามารถใช้การบันทึกขั้นต่ำส่งผลให้มีการบันทึกทุกแถวที่แทรกแต่ละรายการในไฟล์บันทึกของ tempdb เมื่อใช้ร่วมกับตารางชั่วคราวทั่วโลก / ตารางปกติ ในขณะที่ตารางชั่วคราวในพื้นที่ / SELECT INTO/ INSERT INTO ... WITH(TABLOCK)สามารถใช้การบันทึกขั้นต่ำ

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