MSSQL中CTE,临时表和表变量的区别

时间:2017-01-12 15:00:12

标签: sql sql-server performance common-table-expression temp-tables

所有用于临时存储数据。

这三种类型的临时表是否有任何性能差异(时间复杂度和空间复杂度)?

性能问题应取决于结果是保存在磁盘还是内存中。

我搜索了很多但没有得到满意的答案。

2 个答案:

答案 0 :(得分:2)

CTE-常用表表达式 CTE代表通用表表达式。它是SQL Server 2005引入的。它是一个临时结果集,通常可能是复杂子查询的结果。与临时表不同,它的生命仅限于当前查询。它是使用WITH语句定义的。 CTE提高了可读性,并简化了复杂查询和子查询的维护。始终以分号开始CTE。

With CTE1(Address, Name, Age)--Column names for CTE, which are optional
AS
(
SELECT Addr.Address, Emp.Name, Emp.Age from Address Addr
INNER JOIN EMP Emp ON Emp.EID = Addr.EID
)
SELECT * FROM CTE1 --Using CTE 
WHERE CTE1.Age > 50
ORDER BY CTE1.NAME

何时使用CTE? 这用于存储复杂子查询的结果以备将来使用。

这也用于创建递归查询。

临时表 在SQL Server中,临时表是在运行时创建的,您可以执行在普通表上可以执行的所有操作。这些表在Tempdb数据库中创建。根据范围和行为,临时表分为以下两种类型-

本地温度表 本地临时表仅可用于创建表的SQL Server会话或连接(表示单个用户)。当创建表的会话关闭时,这些将自动删除。本地临时表名称以单个井号(“#”)开头。

CREATE TABLE #LocalTemp
(
 UserID int,
 Name varchar(50), 
 Address varchar(150)
)
GO
insert into #LocalTemp values ( 1, 'Shailendra','Noida');
GO
Select * from #LocalTemp

本地临时表的范围存在于当前用户的当前会话意味着当前查询窗口。如果您将关闭当前查询窗口或打开一个新的查询窗口并尝试查找上面创建的临时表,则会出现错误。

全局温度表 全局临时表可用于所有SQL Server会话或连接(意味着所有用户)。这些可以由任何SQL Server连接用户创建,并且在所有SQL Server连接都关闭后会自动将其删除。全局临时表名称以双井号(“ ##”)开头。

CREATE TABLE ##GlobalTemp
(
 UserID int,
 Name varchar(50), 
 Address varchar(150)
)
GO
insert into ##GlobalTemp values ( 1, 'Shailendra','Noida');
GO
Select * from ##GlobalTemp

全局临时表对所有SQL Server连接可见,而本地临时表仅对当前SQL Server连接可见。

表格变量 这就像变量一样,对于特定的一批查询执行存在。一旦批量淘汰,它将被丢弃。这也是在Tempdb数据库中创建的,而不是在内存中创建的。这还允许您在声明表变量时创建主键身份,但不能创建非聚集索引。

 GO
 DECLARE @TProduct TABLE
 (
 SNo INT IDENTITY(1,1),
 ProductID INT,
 Qty INT
 ) 
 --Insert data to Table variable @Product 
 INSERT INTO @TProduct(ProductID,Qty)
 SELECT DISTINCT ProductID, Qty FROM ProductsSales ORDER BY ProductID ASC 
 --Select data
 Select * from @TProduct

 --Next batch
 GO
 Select * from @TProduct --gives error in next batch

注意 临时表是在Tempdb数据库中物理创建的。这些表既可以用作普通表,也可以具有约束,像普通表一样具有索引。

CTE是一个命名的临时结果集,用于处理复杂的子查询数据。这是为了陈述的范围而存在。这是在内存而不是Tempdb数据库中创建的。您无法在CTE上创建任何索引。

表变量的作用类似于变量,并且存在于特定批次的查询执行中。一旦批量淘汰,它将被丢弃。这也是在Tempdb数据库中创建的,而不是在内存中创建的。

答案 1 :(得分:0)

涵盖所有细节的相当广泛的主题。以下是一些高级别的差异,可以为您提供更多的研究方法。

CTE是同一查询的一部分,应该被认为与子查询非常相似。 CTE允许更好的可读性和代码重用(相同的CTE可以在整个查询的不同部分中重用)。

表变量和临时表应该被认为是类似的真实表,但具有使SQL服务器能够快速对它们进行操作的优化,尤其是在与相对较小的数据集一起使用时。请注意,尽管这些操作是针对tempdb进行的,但这并不意味着存储在此处的数据实际上是持久存储到磁盘上的。对于每个新版本的SQL Server,都有额外的优化(例如内存优化表),以使这些构造更快,特别是对于简化复杂查询的主线用例。

有关此主题的更多信息,请参阅此处: https://www.brentozar.com/archive/2014/06/temp-tables-table-variables-memory-optimized-table-variables/