CTE 中的 SQL Server 视图导致性能不佳
Posted
技术标签:
【中文标题】CTE 中的 SQL Server 视图导致性能不佳【英文标题】:SQL Server view inside CTE causing poor performance 【发布时间】:2013-06-28 15:40:06 【问题描述】:当我在 CTE 中使用视图时,每个引用 CTE 的子查询似乎都会重新查询该视图。每个子查询都有大量的执行计划重复。从表中选择时不是这种情况。这是预期的吗?有什么办法可以解决吗?
WITH cte AS (
SELECT v.id
FROM test_view AS v
)
SELECT TOP 25 *,
(SELECT COUNT(*) FROM cte) AS subquery
FROM cte
我正在使用 SQL Server 2005
编辑:
我正在尝试使用以下查询从页面中的视图中获取数据。我需要视图中的总行数、匹配搜索的行数以及匹配行的子集。这在从表中选择时效果很好,但使用视图会导致 CTE 重复执行。我试图通过 Martin 的答案中的链接以各种不同的方式强制中间物化,但没有任何运气。
WITH tableRecords AS (
SELECT *
FROM example_view
),
filteredTableRecords AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id ASC) AS tableRecordNumber
FROM tableRecords
WHERE 1 = 1
)
SELECT *,
(SELECT COUNT(*) FROM tableRecords) AS totalRecords,
(SELECT COUNT(*) FROM filteredTableRecords) AS totalDisplayRecords
FROM filteredTableRecords
WHERE tableRecordNumber BETWEEN 1 AND 25
ORDER BY tableRecordNumber ASC
【问题讨论】:
【参考方案1】:是的,这在很大程度上是预期的。
见Provide a hint to force intermediate materialization of CTEs or derived tables
对于您问题中的查询,您可以这样做
WITH CTE AS
(
SELECT v.id,
count(*) OVER () AS Cnt
FROM test_view AS v
)
SELECT TOP 25 *
FROM CTE
ORDER BY v.id
【讨论】:
感谢您的链接和答案。不幸的是,我无法使用任何链接方法强制实现 CTE。如果有机会,请查看我上面的编辑。 @davishmcclurg - 优化的最佳方式取决于视图的定义、所涉及的表的大小、过滤器表达式的性质和可用索引。没有一种方法永远是最好的。【参考方案2】:我建议你重写你的查询如下
我对您的查询做了一些改进
-
删除 where 1=1,没有必要,因为它总是正确的。
每次执行 sql 脚本时都会调用 select 子句中的子查询,因此您实际上可以使用交叉应用来提高性能。
;WITH tableRecords AS(
SELECT *
FROM example_view
),
filteredTableRecords AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id ASC) AS tableRecordNumber
FROM tableRecords
),TotalNumber
(
SELECT (SELECT COUNT(1) FROM tableRecords) AS totalRecords,
(SELECT COUNT(1) FROM filteredTableRecords) AS totalDisplayRecords
)
SELECT *
FROM filteredTableRecords F
CROSS APPLY TotalNumber AS T
WHERE tableRecordNumber BETWEEN 1 AND 25
ORDER BY tableRecordNumber ASC
【讨论】:
以上是关于CTE 中的 SQL Server 视图导致性能不佳的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server LEFT OUTER JOIN 查询性能
sql server数据库性能优化之2-避免使用CTE公用表达式的递归by zhang502219048
将 SQL Server 中的递归 CTE 转换为 netezza