логічне зчитування в глобальній таблиці темпів, але не в таблиці темпів на рівні сеансу


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не показує статистики вводу / виводу для таблиці темп. Однак, вставляючи в ##t1 does, показує статистику I / O для тимчасової таблиці.

SET STATISTICS IO, TIME ON;
GO

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

Вихід статистики:

Час розбору та компіляції SQL Server: 
   Час процесора = 0 мс, минулий час = 1 мс.
Таблиця 's1'. Кількість сканувань 1, логічне зчитування 19, фізичне зчитування 0, зчитування вперед-зчитування 0, логічне зчитування лобі 0, лобічне фізичне зчитування 0, лобічне зчитування попереднє зчитування 0.

 Часи виконання SQL Server:
   Час процесора = 16 мс, минулий час = 9 мс.

(10000 рядків зачеплені)
INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;
Час розбору та компіляції SQL Server: 
   Час процесора = 0 мс, минулий час = 1 мс.
Таблиця '## t1'. Кількість сканувань 0, логічне зчитування 10016, фізичне зчитування 0, зчитування вперед-зчитування 0, логічне зчитування лобі 0, лобічне фізичне зчитування 0, лобічне зчитування попереднє зчитування 0.
Таблиця 's1'. Кількість сканувань 1, логічне зчитування 19, фізичне зчитування 0, зчитування вперед-зчитування 0, логічне зчитування лобі 0, лобічне фізичне зчитування 0, лобічне зчитування попереднє зчитування 0.

 Часи виконання SQL Server:
   Час процесора = 47 мс, минулий час = 45 мс.

(10000 рядків зачеплені)

Чому в таблиці ## 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)час запуску під час виконання вищезазначеного запиту повертається ~ 1М рядків.

введіть тут опис зображення

Одна 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 
);

Заповнення його 1М-записами

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.

Пол Уайт відповіді пояснюючи логічні зчитування повідомили про глобальні тимчасових таблицях

Як правило, логічні зчитування повідомляються для цільової таблиці, коли вставка мінімально не реєструється.

Ці логічні читання пов'язані з пошуку місця в існуючій структурі для додавання нових рядків. Міні-зафіксовані вставки використовують механізм групового завантаження, який виділяє цілі нові сторінки / розширення (і тому не потрібно читати цільову структуру таким же чином).


Висновок

Висновок полягає в INSERT INTOтому, що не в змозі використовувати мінімальний журнал, що призводить до реєстрації кожного вставленого рядка окремо у файлі журналу tempdb при використанні у поєднанні з глобальною таблицею темпів / звичайною таблицею. Тоді як місцева таблиця темпів / SELECT INTO/ INSERT INTO ... WITH(TABLOCK)може використовувати мінімальний журнал.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.