在 SQL Server 中使用临时表比派生表有优势吗?

nor*_*tos 8 performance sql-server-2008 sql-server derived-tables temporary-tables query-performance

我读到派生表比临时表具有更好的性能,但无论如何许多 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;
Run Code Online (Sandbox Code Playgroud)

派生表

/*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;
Run Code Online (Sandbox Code Playgroud)

临时表

/*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;
Run Code Online (Sandbox Code Playgroud)

Ant*_*rds 6

@user16484 已经将您引导至评论中的哪一个具有更好的性能:派生表或临时表

另请参阅临时表“vs”表变量“vs”CTE。它还包括派生表。

快速总结:#temp 表可以被索引,可以有唯一的索引/约束,可以在同一个查询中被多次引用,可以被多个查询引用(FROM 或 JOIN)。派生表可以在一个查询中被引用(FROM 或 JOIN)一次。

在性能方面,取出 Profiler for SQL:BatchCompleted 和 RPC:Completed,观察 Read、Write、CPU 和 Duration 列,看看派生表、#temp 表和索引 #temp 表的几次运行有何作用每个特定的查询。

一般来说 - 如果您要多次使用它,#temp 表会胜出。如果您要加入很多表,#temp 表可能会胜出。如果您只加入几个表,派生表有合理的获胜机会。基准它!


小智 6

通常,这取决于您的特定查询和临时结果的大小。

对于给定的特定场景,即分页,临时表是完全没有必要的。为什么要将 1000 行保存到临时表中,然后只返回第 200 行?在这种情况下使用“派生”表或 CTE 效率更高,因为完整的结果集不必存储在任何地方,或者在大多数情况下甚至生成。例如,当请求 200 行的第一页时,只需要从基表中检索前 200 行(假设现有索引可以支持查询中请求的排序顺序)。