Pourquoi tronquer une table temporaire à la fin de la procédure stockée qui lui crée un espace tempdb libre plus rapidement?

12

SQL Server met en cache les tables temporaires créées dans les procédures stockées et les renomme simplement lorsque la procédure se termine et est ensuite exécutée. Ma question porte sur le moment où l'espace tempdb est libéré. J'ai lu que le tableau est tronqué à la fin de la procédure . J'ai lu dans les commentaires que cela est géré par session et j'ai vu une question sur la nécessité ou non d'un nettoyage sur MSDN . Mais que se passe-t-il s'il n'est jamais exécuté deux fois par la même session?

J'ai également entendu dire qu'il existe un processus de récupération de place en arrière-plan qui libère cet espace une fois que la table est hors de portée.

La troncature d'une table temporaire à la fin de la procédure stockée qui la crée semble entraîner la libération plus rapide de l'espace utilisé par la table dans tempdb que si aucune instruction tronquée n'est utilisée, malgré les attentes contraires. Pourquoi?

Quelles seraient les implications relatives aux performances de l'utilisation ou de la non-utilisation d'une telle instruction tronquée? Lorsque vous utilisez l'isolement SNAPSHOT, tempdb est souvent souligné et je pense que libérer l'espace utilisé dans tempdb à partir d'une grande table temporaire le plus tôt possible empêcherait une croissance autrement inutile de tempdb. Ces économies d'espace potentielles se feraient-elles au détriment des performances?

Voici du code pour reproduire le problème (principalement de @TheGameiswar, avec quelques modifications):

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

Les lignes commentées ont été laissées commentées pour certains passages et non commentées pour d'autres. Lorsque le a TRUNCATEété commenté, il a fallu entre 2,25 et 4,5 secondes pour que les résultats de la tempdb.sys.dm_db_file_space_usagerequête (4472 pages de plus et 34,9375 Mo de plus) correspondent au résultat avant l'exécution de la procédure. Avec les lignes (y compris les TRUNCATE) non commentées, cela n'a pris que 0,11 à 0,9 seconde. Ces résultats proviennent d'un système en direct, avec une légère croissance des données dans la table source au cours de cette expérience.

Exemple de sortie avec le code commenté (2,69 secondes de la première à la dernière entrée "finale"):

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

Exemples de résultats avec le code non commenté (0,11 seconde de la première à la dernière entrée "finale"):

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
la source

Réponses:

12

La troncature d'une table temporaire à la fin de la procédure stockée qui la crée semble entraîner la libération plus rapide de l'espace utilisé par la table dans tempdb que si aucune instruction tronquée n'est utilisée, malgré les attentes contraires. Pourquoi?

Si la table temporaire est suffisamment grande ( plus de 128 extensions ), les désallocations de pages physiques sont différées et effectuées par une tâche système en arrière-plan. Cela est vrai, qu’un explicite TRUNCATE TABLEsoit utilisé ou non.

La seule différence est un petit détail d'implémentation. Une explicite TRUNCATE TABLEse produit pour créer une tâche avec un minuteur plus court que la tâche de suppression différée (sinon identique) créée par le nettoyage temporaire de la table:

Pile d'appels parce que les gens les aiment

Que ce soit par accident ou par conception, on peut le deviner. Cela pourrait bien sûr changer à tout moment, car ce niveau de détail va bien au-delà de la surface de produit prise en charge.

Si vous désactivez la suppression différée globalement avec un indicateur de trace (principalement) non documenté:

DBCC TRACEON (671, -1);

... les désallocations sont effectuées de manière synchrone dans les deux cas, et vous ne verrez aucune différence de timing.

Quelles seraient les implications relatives aux performances de l'utilisation ou de la non-utilisation d'une telle instruction tronquée? Lorsque vous utilisez l'isolement SNAPSHOT, tempdb est souvent souligné et je pense que libérer l'espace utilisé dans tempdb à partir d'une grande table temporaire le plus tôt possible empêcherait une croissance autrement inutile de tempdb. Ces économies d'espace potentielles se feraient-elles au détriment des performances?

Je doute sérieusement que cela fasse une grande différence dans les deux cas. Si tempdb est dimensionné de manière appropriée pour les besoins de pointe de votre charge de travail, que la baisse différée se produise après une seconde ou trois ne devrait pas avoir d'importance. Le même travail est effectué; c'est juste une petite différence de timing.

D'un autre côté: si vous vous sentez plus à l'aise TRUNCATE TABLEsur les tables temporaires à la fin de vos procédures stockées, allez-y. Je ne suis au courant d'aucun inconvénient particulier à le faire.

Paul White 9
la source