Я читал, что производные таблицы имеют лучшую производительность, чем временные таблицы, но в любом случае многие разработчики SQL Server предпочитают вторые. Почему? Я должен делать запросы с большими данными (миллионы записей), и я хочу быть уверен, что я использую лучший выбор.
CREATE TABLE A(
id BIGINT IDENTITY(1,1) NOT NULL,
field1 INT NOT NULL,
field2 VARCHAR(50) NULL,
);
CREATE TABLE B(
id INT IDENTITY(1,1) NOT NULL,
field1 VARCHAR(10) NULL,
field2 INT NULL
);
INSERT INTO A
(field1,field2)
VALUES
(1,'a'),(2,'b'),(3,'c'),(2,'d'),(5,'e'),
(6,'f'),(7,'g'),(8,'h'),(9,'i'),(2,'j');
INSERT INTO B
(field1,field2)
VALUES
('a',1),('b',2),('c',3),('d',4),('e',5),
('f',6),('g',7),('h',8),('i',9),('j',2),('k',3);
DECLARE @begin INT=0,@end INT=200;
Производные таблицы
/*derived tables*/
SELECT
C.id,C.field1,C.field2,C.field3
FROM
(
SELECT
A.id,A.field1,A.field2,B.field2 AS field3,
ROW_NUMBER() OVER (ORDER BY A.id) AS iRow
FROM
A INNER JOIN B ON A.field1=B.id
) C
WHERE iRow BETWEEN @begin AND @end;
Временные столы
/*temporary tables*/
CREATE TABLE #C (
iRow INT IDENTITY(1,1),
id bigint,
field1 INT,
field2 VARCHAR(50),
field3 INT );
INSERT INTO #C
(id,field1,field2,field3)
SELECT TOP 1000
A.id,A.field1,A.field2,B.field2
FROM
A INNER JOIN B ON A.field1=B.id
ORDER BY
A.id;
SELECT id,field1,field2,field3
FROM #C
WHERE iRow BETWEEN @begin AND @end;
DROP TABLE #C;
SELECT TOP 1000
без каких-либоORDER BY
, это не хорошо. Я думаю, что вам нужно добавитьORDER BY A.id;
для двух способов, чтобы быть эквивалентными.Ответы:
@ user16484 уже направил вас к тому, какой из них имеет лучшую производительность: производные таблицы или временные таблицы в комментарии.
Также см. Temp Table 'vs' Table Variable 'vs' CTE. который также охватывает производные таблицы.
Краткое резюме: таблицы #temp могут быть проиндексированы, могут иметь УНИКАЛЬНЫЕ индексы / ограничения, могут ссылаться более одного раза в одном запросе, на них можно ссылаться (FROM или JOIN) более чем одним запросом. На производные таблицы можно ссылаться (FROM или JOIN) один раз в одном запросе.
С точки зрения производительности извлеките Profiler для SQL: BatchCompleted и RPC: Completed, посмотрите столбцы Read, Write, CPU и Duration и посмотрите, что делает несколько прогонов производных таблиц по сравнению с таблицами #temp и индексированными таблицами #temp каждый конкретный запрос.
В общем - если вы собираетесь использовать его более одного раза, победит таблица #temp. Если вы объединяете много таблиц, вероятно, победит таблица #temp. Если вы объединяете только несколько столов, производная таблица имеет разумный шанс на выигрыш. Оцените это!
источник
В целом, это зависит от ваших конкретных запросов и размера временных результатов.
Для конкретного сценария, который представляет собой пейджинг, временные таблицы совершенно не нужны. Почему вы хотите сохранить 1000 строк во временной таблице только для того, чтобы затем вернуть первые 200? Использование «производной» таблицы или CTE в этом сценарии намного эффективнее, поскольку полный набор результатов не нужно нигде хранить, а в большинстве случаев даже создавать. Например, при запросе 1-й страницы из 200 строк из базовых таблиц нужно будет извлечь только первые 200 строк (при условии, что существующие индексы могут поддерживать порядок сортировки, запрошенный в запросе).
источник