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
一時テーブルを作成するストアドプロシージャの最後で一時テーブルを切り捨てると、テーブルがtempdbで使用する領域が、逆の期待にもかかわらず、切り捨てステートメントを使用しない場合よりも速くデータが解放されるようになります。どうして?
一時テーブルが十分に大きい( 128エクステントを超える )場合、物理ページの割り当て解除は延期され、バックグラウンドシステムタスクによって実行されます。これは、明示的なTRUNCATE TABLE
が使用されているかどうか。
唯一の違いは、小さな実装の詳細です。明示的なTRUNCATE TABLE
は、一時テーブルのクリーンアップによって作成された(それ以外は同じ)遅延ドロップタスクよりも短いタイマーでタスクを作成します。
これが偶然なのか、設計によるものかは、誰もが推測するところです。もちろん、この詳細レベルはサポートされる製品の表面積をはるかに超えているため、いつでも変更される可能性があります。
(ほとんど)文書化されていないトレースフラグを使用して遅延ドロップをグローバルに無効にした場合:
DBCC TRACEON (671, -1);
...割り当て解除は両方のケースで同期的に実行され、タイミングに違いはありません。
このような切り捨てステートメントを使用した場合と使用しない場合の相対的なパフォーマンスへの影響は何ですか? SNAPSHOT分離を使用すると、tempdbにストレスがかかることがよくあります。tempdbで使用されている領域を大きな一時テーブルからできるだけ早く解放すると、tempdbの不要な増加を防ぐことができると思います。この潜在的なスペースの節約は、パフォーマンスを犠牲にして行われますか?
これがどちらの方法でも大きな違いを生むとは思えません。 tempdbがワークロードのピークニーズに合わせて適切にサイズ設定されている場合、遅延ドロップが1秒後に発生するか3秒後に発生するかは重要ではありません。同じ作業が行われます。タイミングのわずかな違いです。
一方、TRUNCATE TABLE
ストアドプロシージャの最後にある一時テーブルで、それに合わせてください。私はこれを行うことの特定の欠点を知りません。