SQL Server выбирает и блокирует временные таблицы

итак, недавно DBA пытается сказать нам, что мы не можем использовать синтаксис

SELECT X, Y, Z
INTO #MyTable
FROM YourTable

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

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

Дополнительная Информация

В настоящее время работает с SQL Server 2005, и скоро будет SQL Server 2008 (Enterprise editions)

8 ответов


этот совет плавает вокруг в течение длительного времени:

узкие места в SQL Server 6.5

многие люди используют SELECT...В запрос чтобы создать временную таблицу, то вот так:

выберите * в #TempTable из SourceTable

пока это работает, он создает блокировки на базе данных tempdb для продолжительность инструкции SELECT (довольно долго, если вы траление через многое данных в источнике стол, и еще дольше, если ВЫБИРАТЬ...INTO находится в начале более длительная явная транзакция) Пока замок на месте, никакой другой пользователь может создавать временные таблицы. Этот фактическое расположение узкого места блокировка системных таблиц tempdb. В дальнейшем версии SQL Server, блокировка модель изменилась и проблема избежавший.

к счастью, это была проблема только для SQL 6.5. Она была исправлена в версии 7.0.


Это, вероятно, будет плавать вокруг в течение длительного времени, питая карманы различных "консультантов". Как и все мифы, в нем есть зерно истины и много BS.

правда: SQL 2000 и предыдущие версии знали проблемы с распределением экстентов в базе данных tempdb. Это утверждение было верным на самом деле во всех базах данных, но более заметным в tempdb из-за некоторого интенсивного использования tempdb. Это задокументировано в KB328551:

когда tempdb база данных сильно используется, SQL Server может возникнуть раздор, когда он пытается выделить страницы.

из системной таблицы sysprocesses вывод, waitresource может отображаться как " 2: 1:1 "(Страница PFS) или "2: 1: 3 "(SGAM Страница.) В зависимости от степени конкуренции это может привести к SQL Сервер не отвечает на запросы короткий период.

эти операции сильно используют tempdb:
Повторное создание и удаление временного таблицы (локальные или глобальный.)
Табличные переменные, использующие tempdb для хранения цели.
Рабочие таблицы, связанные с УКАЗАТЕЛИ.
Рабочие таблицы, связанные с порядок по пунктам.
Рабочие таблицы, связанные с предложением GROUP BY.
Рабочие файлы, связанные с хэш-планами.

тяжелое и значительное использование этих деятельность может привести к разногласиям проблемы.

флаг трассировки -T1118 был добавлен в SQL Server 2000 SP3, который был принуждение SQL использовать циклический алгоритм для распределения смешанных страниц. Этот новый алгоритм, если он соотносится с практикой развертывания базы данных tempdb поверх набора файлов одинакового размера, по одному для каждого процессора, облегчит конфликт. Флаг трассировки все еще присутствует в SQL 2005/2008, хотя его гораздо менее вероятно потребуется.

все остальное об этом мифе в значительной степени BS.

  • использование таблиц #temp вызывает блокировку? Нет. В худшем случае это увеличивается раздор под нагрузкой в SQL 2000 и ранее, но это далеко не говорит о том, что он блокирует что-либо. Сначала вам нужно будет измерить и увидеть, что это так, и если это так, разверните меры по исправлению (выделите один файл tempdb на CPU, сделайте их равными размеру, включите-T1118)..
  • выбирает ... в #temp блок что-то на время выбора? Не реально.
  • выбирает ... в #temp блок что-то на время сохраненного процедура, содержащая выбор? Черт, нет. Просто прочитав это заявление, я расхохотался.

для более подробной информации, есть эта статья: заблуждения вокруг TF1118.


почему бы не сделать следующее?

SELECT X, Y, Z
INTO #MyTable
FROM YourTable
WHERE 1 = 2

оператор будет работать мгновенно-создание таблицы temp и избежать любой возможной блокировки. Затем вы можете вставить в него как обычно:

INSERT #MyTable
SELECT X, Y, Z
FROM YourTable

вы можете получить блокировку, если вы создаете таблицы #temp внутри транзакции. Хотя это обычно не рекомендуется, я видел, что это сделано много.

однако блокировка этой причины находится на некоторых системных таблицах в tempdb, которые не влияют на другие соединения от создания временных таблиц (за исключением, возможно, для версий SQL до 2000?). Это означает, что запуск sp_spacesused в tempdb будет заблокирован, если вы не установите уровень изоляции транзакций для чтения незафиксированных. Также просмотр свойств на tempdb из SSMS завершится с ошибкой и таймаутом, без сомнения, потому что он использует уровень изоляции транзакций Read committed.


Я бы сказал, что отсутствие блокировки означает отсутствие блокировки, что является вашим доказательством. Почему метод, в котором создается временная таблица (CREATE или SELECT ... В) сделать разницу в блокировке TempDB?


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

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

DECLARE @foo TABLE (x int, y int, z int)
INSERT INTO @foo(x, y, z) SELECT x, y, z FROM YourTable

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


SELECT INTO #temp_table удерживает блокировку shema в tempdb на время выполнения оператора, поскольку часть работы, которую он выполняет, - это создание таблицы. Это принципиально отличается от первого создания таблицы с помощью CREATE TABLE #.... и затем запуск набора на основе вставки. SELECT INTO имеет преимуществ перед INSERT, в частности, операция минимально регистрируется, если модель восстановления базы данных является простой или объемный журнал.


в то время как SELECT INTO был исправлен от блокировки tempdb, я бы использовал осторожность при написании такого кода, как при тестировании некоторые системные таблицы блокируются.

ссылка: http://www.sqlservercentral.com/Forums/Topic1642797-2799-1.aspx