グローバルレベルの一時テーブルでは論理読み取り、セッションレベルの一時テーブルでは読み取り不可


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が表示されません。ただし、intoを挿入すると、一時テーブルの統計I / O ##t1 表示されます。

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。

(10000行が影響を受けました)
INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;
SQL Serverの解析時間とコンパイル時間: 
   CPU時間= 0 ms、経過時間= 1 ms。
テーブル '## t1'。スキャンカウント0、論理読み取り10016、物理読み取り0、先読み読み取り0、LOB論理読み取り0、LOB物理読み取り0、LOB先読み読み取り0。
テーブル 's1'。スキャンカウント1、論理読み取り19、物理読み取り0、先読み読み取り0、LOB論理読み取り0、LOB物理読み取り0、LOB先読み読み取り0。

 SQL Server実行時間:
   CPU時間= 47 ms、経過時間= 45 ms。

(10000行が影響を受けました)

## tempテーブルに挿入しているだけなのに、なぜ## tempテーブルに非常に多くの読み取りがあるのですか?

回答:


11

INSERT INTOとグローバル一時テーブルを使用する場合、最小限のロギングは使用されていません

を使用してグローバル一時テーブルに100万行を挿入する 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行ごとに1つの操作+その他のログデータ。


ローカル一時テーブルでの同じ挿入

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

によって返される最大700行まで SELECT * FROM fn_dblog(NULL, NULL)

ここに画像の説明を入力してください

最小限のロギング


を使用してグローバル一時テーブルに100万行を挿入する 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)は作成セッション専用なので、テーブルロックヒントは必要ありません。tempdbで作成されたグローバル一時テーブル(## temp)または通常テーブル(dbo.temp)には、複数のセッションからアクセスできるため、テーブルロックヒントが必要です。

これをテストするための通常のテーブルを作成します。

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

100万件のレコードで埋める

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

このテーブルで100万回を超える論理読み取り

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.