Есть ли преимущества использования временных таблиц по сравнению с производными таблицами в SQL Server?


8

Я читал, что производные таблицы имеют лучшую производительность, чем временные таблицы, но в любом случае многие разработчики 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;

1
У вас есть SELECT TOP 1000без каких-либо ORDER BY, это не хорошо. Я думаю, что вам нужно добавить ORDER BY A.id;для двух способов, чтобы быть эквивалентными.
ypercubeᵀᴹ

Это просто образец. Цель состоит в том, чтобы показать основную тему моего вопроса.
norgematos

Ответы:


6

@ 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. Если вы объединяете только несколько столов, производная таблица имеет разумный шанс на выигрыш. Оцените это!


6

В целом, это зависит от ваших конкретных запросов и размера временных результатов.

Для конкретного сценария, который представляет собой пейджинг, временные таблицы совершенно не нужны. Почему вы хотите сохранить 1000 строк во временной таблице только для того, чтобы затем вернуть первые 200? Использование «производной» таблицы или CTE в этом сценарии намного эффективнее, поскольку полный набор результатов не нужно нигде хранить, а в большинстве случаев даже создавать. Например, при запросе 1-й страницы из 200 строк из базовых таблиц нужно будет извлечь только первые 200 строк (при условии, что существующие индексы могут поддерживать порядок сортировки, запрошенный в запросе).


1
+1, хотя я бы добавил, что использование производных таблиц также позволяет оптимизатору запросов обрабатывать оба запроса одновременно. Это может быть хорошо или иногда плохо, опять же «в зависимости от конкретного запроса». Вот почему всегда полезно проверять оба (на реальных данных, а не на выборочных данных), а не догадываться :-).
Соломон Руцкий,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.