Por que truncar uma tabela temporária no final do procedimento armazenado que cria mais espaço livre no tempdb?

12

O SQL Server armazena em cache as tabelas temporárias criadas nos procedimentos armazenados e apenas as renomeia quando o procedimento termina e é executado posteriormente. Minha pergunta tem a ver com quando o espaço tempdb é liberado. Eu li que a tabela está truncada no final do procedimento . Li nos comentários que isso é tratado por sessão e vi uma pergunta sobre se a limpeza é necessária ou não, respondida no MSDN . Mas e se nunca for executado pela mesma sessão duas vezes?

Também ouvi dizer que existe um processo de coleta de lixo em segundo plano que libera esse espaço quando a tabela está fora do escopo.

Truncar uma tabela temporária no final do procedimento armazenado que a cria parece causar o espaço que a tabela usa no tempdb para que os dados sejam liberados mais rapidamente do que se nenhuma instrução truncada for usada, apesar das expectativas em contrário. Por quê?

Quais seriam as implicações relativas ao desempenho do uso ou não de uma declaração tão truncada? Ao usar o isolamento SNAPSHOT, o tempdb costuma ser estressado e eu acho que liberar espaço usado no tempdb de uma grande tabela temporária o mais rápido possível impediria o crescimento desnecessário do tempdb. Essa economia de espaço em potencial teria um custo de desempenho?

Aqui está um código para reproduzir o problema (principalmente do @TheGameiswar, com algumas alterações):

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

As linhas comentadas foram deixadas comentadas para algumas execuções e não comentadas para outras. Quando o TRUNCATEcomentário foi comentado, demorou entre 2,25 e 4,5 segundos antes dos resultados da tempdb.sys.dm_db_file_space_usageconsulta (mais 4444 páginas e 34,9375 MB maiores) corresponderem ao resultado antes da execução do procedimento. Com as linhas (incluindo as TRUNCATE) não comentadas, levou apenas cerca de 0,11 a 0,9 segundos. Esses resultados são de um sistema ativo, com um pequeno crescimento de dados na tabela de origem durante este experimento.

Exemplo de saída com o código comentado (2,69 segundos da primeira à última entrada "final"):

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

Resultados de amostra com o código sem comentário (0,11 segundos da primeira à última entrada "final"):

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
Mark Freeman
fonte

Respostas:

12

Truncar uma tabela temporária no final do procedimento armazenado que a cria parece causar o espaço que a tabela usa no tempdb para que os dados sejam liberados mais rapidamente do que se nenhuma instrução truncada for usada, apesar das expectativas em contrário. Por quê?

Se a tabela temporária for grande o suficiente ( mais de 128 extensões ), as desalocações da página física serão adiadas e executadas por uma tarefa do sistema em segundo plano. Isso é verdade se um explícito TRUNCATE TABLEé usado ou não.

A única diferença é um pequeno detalhe de implementação. TRUNCATE TABLEOcorre um explícito para criar uma tarefa com um cronômetro mais curto do que a tarefa descartada adiada (caso contrário idêntica) criada pela limpeza temporária da tabela:

Pilha de chamadas porque pessoas como elas

Se isso é por acaso ou design, é uma incógnita. É claro que poderia mudar a qualquer momento, pois esse nível de detalhe vai muito além da área de superfície do produto suportada.

Se você desativar a queda adiada globalmente com um sinalizador de rastreamento não documentado (principalmente):

DBCC TRACEON (671, -1);

... as desalocações são executadas de forma síncrona nos dois casos, e você não verá nenhuma diferença no tempo.

Quais seriam as implicações relativas ao desempenho do uso ou não de uma declaração tão truncada? Ao usar o isolamento SNAPSHOT, o tempdb costuma ser estressado e eu acho que liberar espaço usado no tempdb de uma grande tabela temporária o mais rápido possível impediria o crescimento desnecessário do tempdb. Essa economia de espaço em potencial teria um custo de desempenho?

Eu duvido seriamente que isso faça alguma diferença de qualquer maneira. Se o tempdb for dimensionado adequadamente para as necessidades de pico da sua carga de trabalho, se a queda adiada ocorrerá após um segundo ou três não importará. O mesmo trabalho é feito; é apenas uma pequena diferença no tempo.

Por outro lado: se você se sentir mais confortável usando TRUNCATE TABLEtabelas temporárias ao final de seus procedimentos armazenados, vá em frente. Não estou ciente de nenhuma desvantagem específica em fazer isso.

Paul White 9
fonte