đọc logic trên bảng tạm thời toàn cầu, nhưng không đọc trên bảng tạm thời cấp phiên


11

Hãy xem xét các MCVE đơn giản sau:

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

Khi tôi chạy các phần chèn sau, chèn vào #t1sẽ không hiển thị I / O cho bảng tạm thời. Tuy nhiên, việc chèn vào ##t1 sẽ hiển thị I / O thống kê cho bảng tạm thời.

SET STATISTICS IO, TIME ON;
GO

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

Đầu ra thống kê:

Thời gian phân tích và biên dịch SQL Server: 
   Thời gian CPU = 0 ms, thời gian trôi qua = 1 ms.
Bảng 's1'. Quét số 1, đọc logic 19, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

 Thời gian thực thi máy chủ SQL:
   Thời gian CPU = 16 ms, thời gian trôi qua = 9 ms.

(10000 hàng bị ảnh hưởng)
INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;
Thời gian phân tích và biên dịch SQL Server: 
   Thời gian CPU = 0 ms, thời gian trôi qua = 1 ms.
Bảng '## t1'. Quét số 0, đọc logic 10016, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
Bảng 's1'. Quét số 1, đọc logic 19, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

 Thời gian thực thi máy chủ SQL:
   Thời gian CPU = 47 ms, thời gian trôi qua = 45 ms.

(10000 hàng bị ảnh hưởng)

Tại sao có quá nhiều lượt đọc trên bảng ## temp khi tôi chỉ chèn vào nó?

Câu trả lời:


11

Ghi nhật ký tối thiểu không được sử dụng khi sử dụng INSERT INTOvà bảng tạm thời toàn cầu

Chèn một triệu hàng vào bảng tạm thời toàn cầu bằng cách sử dụng INSERT INTO

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

Khi chạy SELECT * FROM fn_dblog(NULL, NULL)trong khi truy vấn trên đang thực thi, ~ 1M hàng được trả về.

nhập mô tả hình ảnh ở đây

Một LOP_INSERT_ROWthao tác cho mỗi hàng + dữ liệu nhật ký khác.


Việc chèn tương tự vào bảng tạm thời cục bộ

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

Chỉ đi tối đa 700 hàng được trả về bởi SELECT * FROM fn_dblog(NULL, NULL)

nhập mô tả hình ảnh ở đây

Ghi nhật ký tối thiểu


Chèn một triệu hàng vào bảng tạm thời toàn cầu bằng cách sử dụng SELECT INTO

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

nhập mô tả hình ảnh ở đây

SELECT INTO một bảng tạm thời toàn cầu với hồ sơ 10k

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

Thống kê thời gian và 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.

Dựa trên blogpost này, chúng tôi có thể thêm TABLOCKđể bắt đầu đăng nhập tối thiểu trên bảng heap

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

Đọc logic thấp

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)

Một phần câu trả lời của @PaulWhite về cách đạt được ghi nhật ký tối thiểu trên các bảng tạm thời

Không. Các bảng tạm thời cục bộ (#temp) là riêng tư đối với phiên tạo, do đó không cần có gợi ý khóa bảng. Một gợi ý khóa bảng sẽ được yêu cầu cho một bảng tạm thời toàn cầu (## temp) hoặc một bảng thông thường (dbo.temp) được tạo trong tempdb, bởi vì chúng có thể được truy cập từ nhiều phiên.

Tạo một bảng thông thường để kiểm tra điều này:

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

Làm đầy nó với các bản ghi 1M

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

> 1M đọc logic trên bảng này

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.

Câu trả lời của Paul White giải thích các lần đọc logic được báo cáo trên bảng tạm thời toàn cầu

Nói chung, các lần đọc logic được báo cáo cho bảng đích khi chèn không được ghi lại tối thiểu.

Những lần đọc logic này được liên kết với việc tìm một vị trí trong cấu trúc hiện có để thêm các hàng mới. Các phần chèn được ghi nhật ký tối thiểu sử dụng cơ chế tải hàng loạt, phân bổ toàn bộ trang / phạm vi mới (và do đó không cần phải đọc cấu trúc đích theo cùng một cách).


Phần kết luận

Kết luận INSERT INTOlà không thể sử dụng ghi nhật ký tối thiểu, dẫn đến việc ghi nhật ký từng hàng được chèn riêng lẻ vào tệp nhật ký của tempdb khi được sử dụng kết hợp với bảng tạm thời / bảng bình thường. Trong khi đó bảng tạm thời cục bộ / SELECT INTO/ INSERT INTO ... WITH(TABLOCK)có thể sử dụng ghi nhật ký tối thiểu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.