2009-05-13 5 views
26

Мне было интересно о временных таблицах в sp и о том, как все это может повлиять на параллелизм. SP, сделанный на сервере MSSQL 08.Временные таблицы в хранимых процедурах

Если у меня есть SP, где я создать временную таблицу и поместите его снова, как это:

BEGIN 

CREATE TABLE #MyTempTable 
(
    someField int, 
    someFieldMore nvarchar(50) 
) 

... Use of temp table here 
... And then.. 

DROP TABLE #MyTempTable 

END 

Это СП будет называться очень и очень часто, поэтому мой вопрос может ли когда-нибудь возникают проблемы параллелизма здесь?

ответ

28

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

+0

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

+0

Но производительность мудрая есть основные проблемы параллелизма. – tpower

+1

@tpower: Мое понимание OP в основном касалось изменения общего состояния и проблем с потоками. Очевидно, что производительность будет зависеть. –

17

Возможно.

Временные таблицы с префиксом # (# пример) хранятся на основе сеанса. Поэтому, если ваш код снова вызовет хранимую процедуру при запуске другого вызова (например, фоновые потоки), вызов create завершится неудачно, потому что он уже существует.

Если вы действительно обеспокоены использовать табличную переменную вместо

DECLARE @MyTempTable TABLE 
(
    someField int, 
    someFieldMore nvarchar(50) 
) 

Это будет специфичен для «экземпляра» этого вызова хранимой процедуры.

+2

Вы не можете повторно использовать сеанс SQL, независимо от того, что клиент пытается сделать. – gbn

+0

"(#пример) хранятся на основе сеанса" И сеансы основаны на соединении? –

+0

Благодарим за эту очистку gbn –

7

Не совсем, и я говорю о SQL Server. Временная таблица (с единственным #) существует и видна в пределах области, в которой она создана (с привязкой к области). Каждый раз, когда вы вызываете свою хранимую процедуру, создается новая область, и поэтому временная таблица существует только в этой области. Я считаю, что временные таблицы также видны хранимым процедурам и udfs, которые также вызываются в пределах этой области. Если вы, однако, используете double pound (##), то они становятся глобальными в пределах вашего сеанса и поэтому видны другим исполняемым процессам как часть сеанса, в котором создана временная таблица, и вам придется подумать, есть ли возможность доступа к таблице temp одновременно желательно или нет.

-1

База данных использует ту же самую блокировку для всех #temp-таблиц, поэтому, если вы используете много, вы столкнетесь с проблемами взаимоблокировки. Лучше использовать переменные @ table для параллелизма.

+1

-1 Функция блокировки не была правдой, поскольку SQL Server 6.5 –

-1

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

Используйте таблицы #temp, если вам нужно получить доступ к данным из подчиненной хранимой процедуры (это злая глобальная переменная к сохраненной цепочке вызовов процесса), и у вас нет другого чистого способа передачи данных между хранимыми процедурами. Кроме того, используйте его, если вам нужен вторичный индекс (хотя, на самом деле спросите себя, если это #temp таблица, если вам нужно больше, чем один индекс)

Если вы сделаете это, всегда объявить таблицу #temp в верхней функции. SQL заставит перекомпилировать ваш сохраненный proc, когда он увидит инструкцию create table .... так что если у вас есть объявление таблицы #temp в середине хранимой процедуры, вы сохранили proc, который должен прекратить обработку и перекомпилировать.

+1

-1 Нет, временные объекты (таблицы и переменные) обычно кэшируются в SQL Server 2005 и последующих версиях, поэтому избегается перекомпиляция. См. Http://sqlblog.com/blogs/paul_white/archive/2012/08/17/temporary-object-caching-explained.aspx и http://technet.microsoft.com/en-us/library/cc966545.aspx например –

0

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

«#table_temporal

» ## table_global

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

После этого не возникает проблем.

2

Для всех тех, кто рекомендует использовать переменные таблицы, будьте осторожны при этом. Переменная таблицы не может быть проиндексирована, тогда как временная таблица может быть. Переменная таблицы лучше всего использовать при работе с небольшими объемами данных, но если вы работаете с более крупными наборами данных (например, 50 тыс. Записей), то временная таблица будет намного быстрее, чем переменная таблицы.

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

например. создать ргос работника AS НАЧАТЬ - сделать что-то здесь END

create proc wrapper AS 
BEGIN 
    Create table #... 
    BEGIN TRY 
     exec worker 
     exec worker2 -- using same temp table 
     -- etc 
    END TRY 
    END CATCH 
     -- handle transaction cleanup here 
     drop table #... 
    END CATCH 
END 
Смежные вопросы