web-dev-qa-db-ja.com

一時テーブルを作成するストアドプロシージャの最後で一時テーブルを切り捨てると、tempdbスペースの解放が速くなるのはなぜですか?

SQL Serverは、ストアドプロシージャ内で作成された一時テーブルをキャッシュし、プロシージャが終了してその後実行されたときに名前を変更するだけです。 tempdbスペースが解放されるタイミングに関する質問です。テーブルが 手順の最後で切り捨てられている であることを読みました。私はこれを セッションごとに処理される であるとコメントで読み、クリーンアップが必要かどうかについての質問を見ました MSDNで回答 。しかし、同じセッションで2回実行されない場合はどうでしょうか。

また、テーブルがスコープ外になると、そのスペースを解放するバックグラウンドガベージコレクションプロセスがあると聞きました。

一時テーブルを作成するストアドプロシージャの最後で一時テーブルを切り捨てると、テーブルがtempdbで使用する領域が、逆の期待にもかかわらず、切り捨てステートメントを使用しない場合よりも速くデータが解放されるようになります。どうして?

このような切り捨てステートメントを使用した場合と使用しない場合の相対的なパフォーマンスへの影響は何ですか? SNAPSHOT分離を使用すると、tempdbにストレスがかかることがよくあります。tempdbで使用されている領域を大きな一時テーブルからできるだけ早く解放すると、tempdbの不要な増加を防ぐことができると思います。この潜在的なスペースの節約は、パフォーマンスを犠牲にして行われますか?

これは、問題を再現するためのコードです(主に@TheGameiswarから、いくつかの変更が加えられています)。

SET NOCOUNT ON;
GO
ALTER PROC usp_test
AS
BEGIN
    IF object_id('tempdb..#temp') IS NOT NULL
        DROP TABLE #temp

    SELECT *
    INTO #temp
    FROM [dbo].[Event_28] -- This is a table with 15313 rows, using 35648 KB according to sp_spaceused

    --SELECT SUM(user_object_reserved_page_count) AS [user object pages used]
    --  ,(SUM(user_object_reserved_page_count) * 1.0 / 128) AS [user object space in MB]
    --  ,getdate() AS BeforeTruncate
    --FROM tempdb.sys.dm_db_file_space_usage;
 --   TRUNCATE TABLE #temp
    --SELECT SUM(user_object_reserved_page_count) AS [user object pages used]
    --  ,(SUM(user_object_reserved_page_count) * 1.0 / 128) AS [user object space in MB]
    --  ,getdate() AS AfterTruncate
    --FROM tempdb.sys.dm_db_file_space_usage;

END
GO

SELECT SUM(user_object_reserved_page_count) AS [user object pages used]
    ,(SUM(user_object_reserved_page_count) * 1.0 / 128) AS [user object space in MB]
    ,getdate() AS 'before'
FROM tempdb.sys.dm_db_file_space_usage;

EXEC usp_test
GO

SELECT SUM(user_object_reserved_page_count) AS [user object pages used]
    ,(SUM(user_object_reserved_page_count) * 1.0 / 128) AS [user object space in MB]
    ,getdate() AS 'final'
FROM tempdb.sys.dm_db_file_space_usage;
GO 40

一部の実行ではコメント化された行がコメント化されたままになり、他の実行ではコメント化されませんでした。 TRUNCATEがコメント化された場合、tempdb.sys.dm_db_file_space_usageクエリの結果(さらに4447ページ、34.9375 MB大きい)の結果がプロシージャの実行前の結果と一致するまでに、2.25〜4.5秒かかりました。行(TRUNCATEを含む)のコメントを外すと、約0.11〜0.9秒しかかかりませんでした。これらの結果はライブシステムからのもので、この実験中にソーステーブルのデータが若干増加しました。

コードがコメント化された出力例(最初の「最後の」エントリから最後までの2.69秒):

user object pages used user object space in MB                 before
---------------------- --------------------------------------- -----------------------
1536                   12.000000                               2017-10-04 21:03:42.197

Beginning execution loop
user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:42.423

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:42.533

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:42.643

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:42.883

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:42.990

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:43.100

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:43.450

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:43.650

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:43.767

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:43.993

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:44.103

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:44.213

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:44.437

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:44.553

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:44.663

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:44.887

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6000                   46.875000                               2017-10-04 21:03:45.003

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
1536                   12.000000                               2017-10-04 21:03:45.113

コメントなしのコードのサンプル結果(最初の「最後の」エントリから最初の0.11秒):

user object pages used user object space in MB                 before
---------------------- --------------------------------------- -----------------------
1536                   12.000000                               2017-10-04 21:07:39.807

user object pages used user object space in MB                 BeforeTruncate
---------------------- --------------------------------------- -----------------------
6016                   47.000000                               2017-10-04 21:07:39.923

user object pages used user object space in MB                 AfterTruncate
---------------------- --------------------------------------- -----------------------
6016                   47.000000                               2017-10-04 21:07:39.923

Beginning execution loop
user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
6016                   47.000000                               2017-10-04 21:07:40.160

user object pages used user object space in MB                 final
---------------------- --------------------------------------- -----------------------
1536                   12.000000                               2017-10-04 21:07:40.270
12
Mark Freeman

一時テーブルを作成するストアドプロシージャの最後で一時テーブルを切り捨てると、テーブルがtempdbで使用する領域が、逆の期待にもかかわらず、切り捨てステートメントを使用しない場合よりも速くデータが解放されるようになります。どうして?

一時テーブルが十分に大きい( 128エクステントを超える )場合、物理ページの割り当て解除は延期され、バックグラウンドシステムタスクによって実行されます。これは、明示的なTRUNCATE TABLEが使用されているかどうか。

唯一の違いは、小さな実装の詳細です。明示的なTRUNCATE TABLEは、一時テーブルのクリーンアップによって作成された(それ以外は同じ)遅延ドロップタスクよりも短いタイマーでタスクを作成します。

Call stack because people like them

これが偶然なのか、設計によるものかは、誰もが推測するところです。もちろん、この詳細レベルはサポートされる製品の表面積をはるかに超えているため、いつでも変更される可能性があります。

(ほとんど)文書化されていないトレースフラグを使用して遅延ドロップをグローバルに無効にした場合:

DBCC TRACEON (671, -1);

...割り当て解除は両方のケースで同期的に実行され、タイミングに違いはありません。

このような切り捨てステートメントを使用した場合と使用しない場合の相対的なパフォーマンスへの影響は何ですか? SNAPSHOT分離を使用すると、tempdbにストレスがかかることがよくあります。tempdbで使用されている領域を大きな一時テーブルからできるだけ早く解放すると、tempdbの不要な増加を防ぐことができると思います。この潜在的なスペースの節約は、パフォーマンスを犠牲にして行われますか?

これがどちらの方法でも大きな違いを生むとは思えません。 tempdbがワークロードのピークニーズに合わせて適切にサイズ設定されている場合、遅延ドロップが1秒後に発生するか3秒後に発生するかは重要ではありません。同じ作業が行われます。タイミングのわずかな違いです。

一方、TRUNCATE TABLEストアドプロシージャの最後にある一時テーブルで、それに合わせてください。私はこれを行うことの特定の欠点を知りません。

12
Paul White 9