считается ли разделение временных таблиц между процедурами плохим? - PullRequest
4 голосов
/ 14 июля 2009

у меня 2 процедуры. Один, который создает временную таблицу, и другой (или несколько других), которые используют временную таблицу, созданную в первом процессе. Это считается плохой формой? Я иду в существующую кодовую базу здесь, и она часто использует этот шаблон. Это, конечно, беспокоит меня, но я не могу сказать, что это явно плохая идея. Я просто нахожу это раздражающим паттерном - что-то пахнет гнилым, но я не могу сказать что. Я бы предпочел построить таблицу локально, а затем заполнить ее с помощью exec. Но для этого нужны проки, которые возвращают только одну таблицу, что необычно в существующей кодовой базе.

Уклоняются ли гуру SQL от такого совместного использования временных таблиц? Если так, то почему? Я пытаюсь сформировать взвешенное мнение по этому поводу и хотел бы получить какой-то вклад.

Был бы вид жизнеспособной альтернативой?

А как насчет производительности? Было бы лучше построить @table локально или построить #table в процессе "fill"?

Здесь хорошо обсуждаются все методы: http://www.sommarskog.se/share_data.html

Ответы [ 8 ]

4 голосов
/ 15 июля 2009

Как парадигма программирования, она уродлива, поскольку включает передачу внеполосных параметров («параметров контекста»), которые явно не вызываются в сигнатурах процедур. Это создает скрытые зависимости и приводит к эффекту спагетти.

Но в конкретном контексте SQL просто нет альтернативы . SQL работает с наборами данных, и вы не можете передавать эти наборы данных как параметры процедуры. У вас есть несколько вариантов:

  • Пройдите через клиента. Слишком очевидно, не реальный вариант.
  • XML или строки с типами разделителей для представления результатов. В любом случае это несерьезный вариант, они могут дать хорошую семантику программирования (т.е. закон Деметра соответствие), но они действительно ужасны, когда производительность вступает в игру.
  • общие таблицы (будь то в tempdb или в appdb), как советует Радж. Вы теряете автоматическое обслуживание #temp (очистка по счетчику ссылок равна 0), и вы должны быть готовы к созданию условий гонки. Кроме того, они могут увеличиваться в размерах без причины (они больше не разбиваются на сессии по отдельным наборам строк, как таблицы #temp).
  • @ таблицы. Они ограничены контекстом объявления (т. Е. Процедурой) и не могут передаваться между процедурами. Я также обнаружил некоторые неприятные проблемы под давлением памяти .
1 голос
/ 15 июля 2009

Иногда это единственный путь. Если вам нужно сделать это, то ДОКУМЕНТ, ДОКУМЕНТ, ДОКУМЕНТ факты. Вот один из способов прояснить ситуацию: поместить определение таблицы в качестве комментария в разделе параметров ...

CREATE PROCEDURE xyz
(
     @param1  int            --REQUIRED, what it does
    ,@param2  char(1)        --OPTIONAL, what it does
    ,@param3  varchar(25)    --OPTIONAL, what it does
    --this temp table is required and must be created in the calling procedure
    --#TempXyz (RowID      int          not null primary key
    --         ,DataValue  varchar(10)  not null
    --         ,DateValue  datetime     null
    --         )
)

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

--** THIS TEMP TABLE IS PASSED BETWEEN STORED PROCEDURES **
--** ALL CHANGES MUST TAKE THIS INTO CONSIDERATION!!!    **
CREATE TABLE #TempXyz 
(RowID      int          not null primary key
,DataValue  varchar(10)  not null
,DateValue  datetime     null
)
1 голос
/ 15 июля 2009

Самая большая проблема с совместным использованием временных таблиц заключается в том, что они вводят внешние зависимости в процедуру, которая может быть не очевидна на первый взгляд. Скажем, у вас есть какая-то процедура p1, которая вызывает процедуру p2, а временная таблица # t1 используется для передачи информации между двумя процедурами. Если вы хотите запустить p2 изолированно, чтобы увидеть, что он делает, вы должны создать «жгут», который определяет # t1, прежде чем вы сможете его запустить. Использование временных таблиц в T-SQL часто эквивалентно использованию глобальных переменных в других языках - не рекомендуется, но иногда неизбежно.

SQL Server 2008 теперь имеет табличные параметры, но Microsoft решила сделать их доступными только для чтения в этом выпуске. Тем не менее, это означает, что вам не нужно использовать временные таблицы в некоторых сценариях, в которых вы были раньше.

Мой совет: используйте их, если нужно, но тщательно документируйте их использование. Если у вас есть какой-то процесс, который зависит от временной таблицы, запустите ее в комментарии.

0 голосов
/ 15 июля 2009

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

Почему работа делится на 2 хранимых процесса? Разве нельзя сделать что-то за 1 процесс?

0 голосов
/ 15 июля 2009

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

CREATE TABLE spid_table
(
   id INT IDENTITY(1, 1) NOT NULL,
   -- Your columns here
   spid INT NOT NULL DEFAULT @@SPID,
   PRIMARY KEY (id)
);

В ваших процедурах вы должны иметь следующий код:

SELECT @var = some_value
FROM spid_table
WHERE -- some condition
AND spid = @@SPID;

и в конце обработки:

DELETE FROM spid_table
WHERE spid = @@SPID;

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

0 голосов
/ 14 июля 2009

Я использовал этот подход в нескольких случаях. Но я всегда объявляю временную таблицу как полностью определенную таблицу, а не используя # tablename.

CREATE TABLE [tempdb].[dbo].[tablename]

при таком подходе легко отслеживать временную таблицу.

Raj

0 голосов
/ 14 июля 2009

Совместное использование временных таблиц - неплохая идея. Но мы должны убедиться, что данные на уровне таблицы не должны обрабатываться двумя процессами одновременно, что приводит к сценарию грязного чтения / записи. Это также поможет иметь единую [централизованную] таблицу и работающие над ней процы для синхронизации данных. Что касается производительности, это правда, что наличие нескольких процессоров, совместно использующих одни и те же временные данные, снизит производительность. Но в то же время наличие отдельных таблиц [в расчете на Proc] приведет к увеличению потребления памяти,

0 голосов
/ 14 июля 2009

Я столкнулся с той же самой проблемой. Что я могу сказать из личного опыта:

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

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

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