CTE内部的SQL Server视图导致性能不佳

时间:2013-06-28 15:40:07

标签: sql sql-server sql-server-2005 view common-table-expression

当我在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。我试图从马丁的答案中以各种不同的方式强制实现中间物化,但没有任何运气。

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

2 个答案:

答案 0 :(得分:2)

是的,这在很大程度上是预期的。

请参阅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

答案 1 :(得分:0)

我建议你重新编写你的查询,如下所示

我对您的查询做了一些改进

  1. 删除1 = 1的地方,这是不必要的,因为它始终是真的。
  2. 每次执行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