Почему обрезка временной таблицы в конце хранимой процедуры ускоряет создание свободного пространства в базе данных tempdb?

12

SQL Server кэширует временные таблицы, созданные в хранимых процедурах, и просто переименовывает их, когда процедура заканчивается и впоследствии выполняется. Мой вопрос касается того, когда освободится пространство tempdb. Я читал, что таблица обрезается в конце процедуры . Я читал в комментариях, что это обрабатывается для каждого сеанса, и видел вопрос о том, нужна ли очистка, на MSDN . Но что, если он никогда не будет выполнен одним и тем же сеансом дважды?

Я также слышал, что есть фоновый процесс сборки мусора, который освобождает это пространство, когда таблица выходит из области видимости.

Усечение временной таблицы в конце создаваемой хранимой процедуры, по-видимому, приводит к тому, что пространство, используемое таблицей в базе данных 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комментарий был закомментирован, потребовалось от 2,25 до 4,5 секунд, прежде чем результаты tempdb.sys.dm_db_file_space_usageзапроса (еще 4472 страницы и 34,9375 МБ) соответствовали результату перед выполнением процедуры. С незакомментированными строками (включая 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

Усечение временной таблицы в конце создаваемой хранимой процедуры, по-видимому, приводит к тому, что пространство, используемое таблицей в базе данных tempdb, для высвобождения данных быстрее, чем если бы не использовался оператор усечения, несмотря на ожидания обратного. Почему?

Если временная таблица достаточно велика ( более 128 экстентов ), освобождение физической страницы откладывается и выполняется фоновой системной задачей. Это верно независимо от того, используется явное TRUNCATE TABLEили нет.

Единственное отличие - крошечная деталь реализации. В явном виде TRUNCATE TABLEсоздается задача с более коротким таймером, чем (иначе идентичная) отложенная задача удаления, созданная путем очистки временной таблицы:

Стек вызовов, потому что люди любят их

Является ли это случайно или дизайном - чье-то предположение. Конечно, он может измениться в любое время, поскольку этот уровень детализации выходит далеко за пределы поддерживаемой поверхности продукта.

Если вы отключите глобальное отложенное удаление с (в основном) недокументированным флагом трассировки:

DBCC TRACEON (671, -1);

... освобождение выполняется синхронно в обоих случаях, и вы не увидите никакой разницы во времени.

Каковы будут относительные последствия для производительности использования или не использования такого усеченного оператора? При использовании изоляции SNAPSHOT, tempdb часто подвергается стрессу, и я думаю, что высвобождение пространства, используемого в tempdb, из большой временной таблицы как можно скорее предотвратит ненужный рост tempdb. Приведет ли эта потенциальная экономия пространства к снижению производительности?

Я серьезно сомневаюсь, что это так или иначе будет иметь большое значение. Если размер базы данных tempdb соответствует пиковым потребностям вашей рабочей нагрузки, не имеет значения, будет ли отложенное падение через одну секунду или три. Та же самая работа сделана; это только небольшая разница во времени.

С другой стороны: если вам удобнее использовать TRUNCATE TABLEвременные таблицы в конце ваших хранимых процедур, сделайте это. Я не знаю ни одного конкретного недостатка в этом.

Пол Уайт 9
источник