繁体   English   中英

使用Sql Server 2008进行子查询缓存

[英]Subquery Caching with Sql Server 2008

我正在使用Sql Server 2008创建存储过程,该存储过程将返回2个结果集。 与第二个查询一样,第一个查询返回一个我想重用的结果集作为子查询(请参见下面的示例)。 但是,由于第一个查询和子查询本质上返回相同的数据,所以我想知道是否可以使用某些缓存机制。 有可能这样做吗? 我正在尝试优化性能。

SELECT * 
FROM   Employees
WHERE  BossId = 1

SELECT * 
FROM   CostCenters
WHERE  EmployeeId IN (
    SELECT EmployeeId 
    FROM   Employees
    WHERE  BossId = 1
)

PS该示例是一个简化的问题。

您可以通过重用查询计划来缓存CTE。 这需要在该函数产生的结果集之间注入Eager Spool Quassnoi在本文中使用了它 ,但目前无法找到更好的示例。 这是有关Eager Spool的另一本好书

据我所知,您将需要为此使用临时表或表变量。 是两者比较

下面使用OUTPUT子句填充表变量,并在一条语句中从中选择。

declare @MatchingResults table
(
EmployeeId int primary key --Other Columns
)

INSERT INTO @MatchingResults
OUTPUT INSERTED.*
SELECT EmployeeId  --Other Columns
FROM   Employees
WHERE  BossId = 1


SELECT * 
FROM   CostCenters
WHERE  EmployeeId IN (
    SELECT EmployeeId 
    @MatchingResults))

表变量是最佳选择。 您还可以通过对子查询使用exists运算符来提高性能,而不是in

-- obviously the columns should match your Employees table
declare @results table (
    employeeId int,
    column1 varchar,
    column2 int
)

insert into @results
select * from Employees
where BossId = 1

-- using exists/not exists performs much better than in
select * from CostCenters
where exists ( select 0
               from @results as r
               where CostCenters.employeeId = r.employeeId )

缓存第一个查询的数据可能不会导致更好的性能。 SQL Server收到查询后,将其分解为简单的步骤,选择适当的索引和运算符,然后使用这些索引检索数据。 通过将第一个查询的数据存储在表变量或临时表中,可以防止SQL Server使用Employees表上的任何索引。

如果使用JOIN将查询重写为等效查询,则更容易了解会发生什么情况

SELECT c.* 
FROM   CostCenters c INNER JOIN Employees e on c.EmployeeId=e.EmployeeId
WHERE e.BossId=1

当SQL Server看到此查询时,它将检查表的统计信息。 如果BossId是高度选择性索引的列,则它可能首先尝试以此过滤。 否则,它将使用EmployeeId列上的任何索引将两个表中的行限制为最小值,然后使用BossId查找正确的行并返回它们。

索引的筛选操作非常快,因为索引仅包含行数据的一个子集,更易于缓存在内存中,并且具有允许快速搜索的物理结构。

在遇到实际的性能问题之前,您真的不应该尝试猜测SQL Server的查询优化器。 大多数时候,您会阻止它选择最佳的执行计划,从而导致性能下降

我能想到的最好的解决方案是选择CTE

http://msdn.microsoft.com/en-us/library/ms190766.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM