簡體   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