Зачем использовать табличную функцию вместо временной таблицы в SQL?

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

Я наткнулся на это: Можно ли использовать хранимую процедуру в качестве подзапроса в SQL Server 2008?

Мой вопрос заключается в том, почему использование табличной функции лучше, чем использование временной таблицы.

Предположим, моя хранимая процедура @SP1

declare @temp table(a int)


insert into @temp 
select a from BigTable 
where someRecords like 'blue%'

update AnotherBigTable
set someRecords = 'were blue'
from AnotherBigTable t 
inner join
@temp
on t.RecordID = @temp.a

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

Спасибо


person Isaac Pounder    schedule 06.12.2012    source источник


Ответы (2)


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

  • функции, которые не могут создавать временные объекты
  • передача табличных данных (наборов) в качестве параметров только для чтения
  • игровая статистика для определенных крайних случаев запроса
  • стабильность плана выполнения (связанная со статистикой, а также с тем фактом, что табличные переменные INSERT INTO не могут использовать параллельный план)
  • до SQL Server 2012 таблицы #temp наследуют параметры сортировки из базы данных tempdb, тогда как переменные @table используют параметры сортировки текущей базы данных.

В остальном таблица #temporary будет работать так же, если не лучше, чем переменная.

Дополнительная литература: Что разница между временной таблицей и табличной переменной в SQL Server?

person RichardTheKiwi    schedule 06.12.2012

Вероятно, уже неактуально... но я могу предложить две вещи, которые используют два разных подхода.

Простой подход 1:


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

declare @temp table(a int, primary key(a))

Простой подход 2:

В этом конкретном случае попробуйте общее табличное выражение (CTE)...

;with

   temp as ( 
      SELECT      a as Id
      FROM        BigTable
      WHERE       someRecords like '%blue'
   ),

 UPDATE    AnotherBigTable
 SET       someRecords = 'were Blue'
 FROM      AnotherBigTable
 JOIN      temp
   ON      temp.Id = AnotherBigTable.RecordId

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

person Will Bellman    schedule 11.02.2014