0

當我在CTE內部使用視圖時,引用CTE的每個子查詢似乎都重新查詢該視圖。每個子查詢都會重複執行大量的執行計劃。從表中選擇時不是這種情況。這是預期的嗎?有什麼辦法可以解決它嗎?CTE導致性能較差的SQL Server視圖

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

是的,這是很大程度上的預期。

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 
+0

感謝您的鏈接和答案。不幸的是,我無法使用任何鏈接的方法強制實現CTE。請檢查我的編輯上面,如果你有機會。 – davishmcclurg

+0

@davishmcclurg - 優化的最佳方式取決於視圖的定義,涉及的表的大小,過濾器表達式的性質和可用的索引。沒有一種方法總是最好的。 –

0

我建議你重新寫你的查詢,如下

有我做了一些改進您的查詢

  1. 去除其中1 = 1,這是不必要的,因爲它是al方式正確。
  2. select子句中的子查詢將在每次執行sql腳本時被調用,因此,實際上可以使用交叉應用來提高性能。

    ;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