¿Por qué truncar una tabla temporal al final del procedimiento almacenado que crea espacio tempdb libre más rápido?

12

SQL Server almacena en caché las tablas temporales creadas dentro de los procedimientos almacenados y simplemente las renombra cuando finaliza el procedimiento y se ejecuta posteriormente. Mi pregunta tiene que ver con cuándo se libera el espacio tempdb. He leído que la tabla se trunca al final del procedimiento . He leído en los comentarios que esto se maneja por sesión y he visto una pregunta sobre si la limpieza es necesaria o no en MSDN . Pero, ¿qué pasa si nunca es ejecutado por la misma sesión dos veces?

También escuché que hay un proceso de recolección de basura en segundo plano que libera ese espacio una vez que la tabla está fuera del alcance.

Truncar una tabla temporal al final del procedimiento almacenado que la crea parece causar el espacio que la tabla usa en tempdb para que los datos se liberen más rápido que si no se usa una declaración truncada, a pesar de las expectativas en contrario. ¿Por qué?

¿Cuáles serían las implicaciones de rendimiento relativo de usar o no usar una declaración tan truncada? Cuando se usa el aislamiento SNAPSHOT, tempdb a menudo está estresado y creo que liberar el espacio utilizado en tempdb desde una tabla temporal grande tan pronto como sea posible evitaría el crecimiento innecesario de tempdb. ¿Este ahorro potencial de espacio vendría a costa del rendimiento?

Aquí hay un código para reproducir el problema (principalmente de @TheGameiswar, con algunos cambios):

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

Las líneas comentadas se dejaron comentadas para algunas ejecuciones y sin comentarios para otras. Cuando TRUNCATEse comentó el comentario, tempdb.sys.dm_db_file_space_usagepasaron entre 2.25 y 4.5 segundos antes de que los resultados de la consulta (4472 páginas más y 34.9375 MB más grandes) coincidieran con el resultado antes de que se ejecutara el procedimiento. Con las líneas (incluida la TRUNCATE) sin comentarios, solo tardó entre 0,11 y 0,9 segundos. Estos resultados provienen de un sistema en vivo, con un pequeño crecimiento de datos en la tabla fuente durante este experimento.

Salida de muestra con el código comentado (2,69 segundos desde la primera hasta la ú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 muestra con el código sin comentarios (0,11 segundos desde la primera hasta la ú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
fuente

Respuestas:

12

Truncar una tabla temporal al final del procedimiento almacenado que la crea parece causar el espacio que la tabla usa en tempdb para que los datos se liberen más rápido que si no se usa una declaración truncada, a pesar de las expectativas en contrario. ¿Por qué?

Si la tabla temporal es lo suficientemente grande ( más de 128 extensiones ), las asignaciones físicas de la página se difieren y se realizan mediante una tarea del sistema en segundo plano. Esto es cierto tanto si TRUNCATE TABLEse usa un explícito como si no.

La única diferencia es un pequeño detalle de implementación. TRUNCATE TABLESucede explícitamente crear una tarea con un temporizador más corto que la tarea de eliminación diferida (por lo demás idéntica) creada por la limpieza temporal de la tabla:

Pila de llamadas porque a las personas les gustan

Si esto es por accidente o por diseño, nadie lo sabe. Por supuesto, podría cambiar en cualquier momento, ya que este nivel de detalle va mucho más allá del área de superficie del producto admitida.

Si deshabilita la caída diferida globalmente con un indicador de rastreo (en su mayoría) no documentado:

DBCC TRACEON (671, -1);

... las desasignaciones se realizan sincrónicamente en ambos casos, y no verá ninguna diferencia en el tiempo.

¿Cuáles serían las implicaciones de rendimiento relativo de usar o no usar una declaración tan truncada? Cuando se usa el aislamiento SNAPSHOT, tempdb a menudo está estresado y creo que liberar el espacio utilizado en tempdb desde una tabla temporal grande tan pronto como sea posible evitaría el crecimiento innecesario de tempdb. ¿Este ahorro potencial de espacio vendría a costa del rendimiento?

Dudo seriamente que esto haga alguna diferencia en ambos sentidos. Si tempdb tiene el tamaño adecuado para las necesidades máximas de su carga de trabajo, si la caída diferida ocurre después de un segundo o tres no debería importar. Se hace el mismo trabajo; Es solo una pequeña diferencia en el tiempo.

Por otro lado: si se siente más cómodo usando TRUNCATE TABLEtablas temporales al final de sus procedimientos almacenados, vaya con eso. No estoy al tanto de ninguna desventaja particular para hacer esto.

Paul White 9
fuente