Consider the following simple 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
When I run the following inserts, inserting into #t1
shows no stats I/O for the temp table. However, inserting into ##t1
does show stats I/O for the temp table.
SET STATISTICS IO, TIME ON;
GO
INSERT INTO #t1 (r)
SELECT r
FROM dbo.s1;
The stats output:
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 1 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 = 9 ms. (10000 rows affected)
INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 1 ms. Table '##t1'. Scan count 0, logical reads 10016, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 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 = 47 ms, elapsed time = 45 ms. (10000 rows affected)
Why are there so many reads on the ##temp table when I'm only inserting into it?