letture logiche sulla tabella temporanea globale, ma non sulla tabella temporanea a livello di sessione


11

Considera il seguente MCVE semplice:

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

Quando eseguo i seguenti inserti, l'inserimento in #t1non mostra alcun I / O di statistiche per la tabella temporanea. Tuttavia, l'inserimento in ##t1 fa mostra previsti I / O per la tabella temporanea.

SET STATISTICS IO, TIME ON;
GO

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

L'output delle statistiche:

Tempo di analisi e compilazione di SQL Server: 
   Tempo CPU = 0 ms, tempo trascorso = 1 ms.
Tabella 's1'. Conteggio scansione 1, letture logiche 19, letture fisiche 0, letture avanti 0, letture logiche lob 0, letture fisiche lob 0, letture read lob 0.

 Tempi di esecuzione di SQL Server:
   Tempo CPU = 16 ms, tempo trascorso = 9 ms.

(10000 righe interessate)
INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;
Tempo di analisi e compilazione di SQL Server: 
   Tempo CPU = 0 ms, tempo trascorso = 1 ms.
Tabella '## t1'. Conteggio scansione 0, letture logiche 10016, letture fisiche 0, letture read-ahead 0, letture log lob 0, letture fisiche lob 0, letture read lob 0.
Tabella 's1'. Conteggio scansione 1, letture logiche 19, letture fisiche 0, letture avanti 0, letture logiche lob 0, letture fisiche lob 0, letture read lob 0.

 Tempi di esecuzione di SQL Server:
   Tempo CPU = 47 ms, tempo trascorso = 45 ms.

(10000 righe interessate)

Perché ci sono così tante letture nella tabella ## temp quando le inserisco solo?

Risposte:


11

La registrazione minima non viene utilizzata durante l'utilizzo INSERT INTOe le tabelle temporanee globali

Inserendo un milione di righe in una tabella temporanea globale usando INSERT INTO

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

Durante l'esecuzione SELECT * FROM fn_dblog(NULL, NULL)mentre la query sopra è in esecuzione, vengono restituite ~ 1 milione di righe.

inserisci qui la descrizione dell'immagine

LOP_INSERT_ROWUn'operazione per ogni altri dati di log fila +.


Lo stesso inserto su una tabella temporanea locale

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

Restituito solo da un massimo di 700 righe SELECT * FROM fn_dblog(NULL, NULL)

inserisci qui la descrizione dell'immagine

Registrazione minima


Inserendo un milione di righe in una tabella temporanea globale usando SELECT INTO

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

inserisci qui la descrizione dell'immagine

SELECT INTO una tabella temporanea globale con record 10k

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

Time and IO Statistics

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.

Sulla base di questo post di blog possiamo aggiungere TABLOCKper avviare la registrazione minima su una tabella heap

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

Letture logiche basse

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)

Parte di una risposta di @PaulWhite su come ottenere una registrazione minima su tabelle temporanee

No. Le tabelle temporanee locali (#temp) sono private per la sessione di creazione, quindi non è richiesto un suggerimento per il blocco delle tabelle. Un suggerimento per il blocco delle tabelle sarebbe necessario per una tabella temporanea globale (## temp) o una tabella normale (dbo.temp) creata in tempdb, poiché è possibile accedervi da più sessioni.

Creazione di una tabella regolare per testare questo:

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

Riempiendo con record 1M

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

> 1M letture logiche su questa tabella

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.

La risposta di Paul White che spiega le letture logiche riportate nella tabella delle temp globali

In genere, le letture logiche vengono riportate per la tabella di destinazione quando l'inserimento non è minimamente registrato.

Queste letture logiche sono associate alla ricerca di un posto nella struttura esistente per aggiungere le nuove righe. Gli inserti con registrazione minima utilizzano il meccanismo di caricamento di massa, che alloca pagine / estensioni completamente nuove (e quindi non è necessario leggere la struttura di destinazione allo stesso modo).


Conclusione

La conclusione è che INSERT INTOnon è in grado di utilizzare la registrazione minima, risultando nella registrazione di ogni riga inserita singolarmente nel file di registro di tempdb quando utilizzata in combinazione con una tabella temporanea globale / tabella normale. Considerando che la tabella temporanea locale / SELECT INTO/ INSERT INTO ... WITH(TABLOCK)è in grado di utilizzare la registrazione minima.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.