SQL Server SELECT INTO и блокировка с помощью временных таблиц - PullRequest
26 голосов
/ 20 августа 2009

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

SELECT X, Y, Z
INTO #MyTable
FROM YourTable

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

Мы пытаемся найти доказательство того, что нам не нужно проходить и делать CREATE TABLE #MyTable ... для всех наших временных таблиц, но ни одна из сторон не может найти доказательства. Я ищу любую информацию, которую имеют ТАКИЕ люди.

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

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

Ответы [ 8 ]

34 голосов
/ 20 августа 2009

Этот совет долго витал вокруг :

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

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

SELECT * INTO #TempTable FROM SourceTable

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

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

17 голосов
/ 20 августа 2009

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

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

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

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

Эти операции интенсивно используют tempdb:
Повторное создание и удаление временных таблицы (локальные или глобальные).
Табличные переменные, которые используют tempdb для хранения цели.
Рабочие столы, связанные с Курсоры.
Рабочие столы, связанные с предложение ORDER BY.
Рабочие таблицы, связанные с предложением GROUP BY.
Рабочие файлы, связанные с HASH PLANS.

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

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

Все остальное в этом мифе в значительной степени относится к БС.

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

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

10 голосов
/ 16 июня 2010

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

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

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

INSERT #MyTable
SELECT X, Y, Z
FROM YourTable
1 голос
/ 02 ноября 2010

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

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

0 голосов
/ 10 марта 2016

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

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

0 голосов
/ 22 января 2010

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

0 голосов
/ 20 августа 2009

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

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

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

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

0 голосов
/ 20 августа 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...