我有它運行在一個OLE-DB查詢鏈接服務器內嵌表值函數,定義適用如下:如何防止交叉的不良優化與內聯表值函數
CREATE FUNCTION [dbo].[fnGetResultsForTag]
(
@elapsedTimeTag NVARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT tag, time, value
FROM PI.piarchive..picount
WHERE tag = @elapsedTimeTag
AND filterexpr = QUOTENAME(@elapsedTimeTag, '''') + ' > NEXTVAL(' + QUOTENAME(@elapsedTimeTag, '''') + ', ''*'')'
AND time BETWEEN (SELECT result FROM PI.pifunction..date WHERE arg1='t-20h') AND (SELECT result FROM PI.pifunction..date WHERE arg1='*')
AND timestep = (SELECT result FROM PI.pifunction..time WHERE arg1='12h')
AND calcbasis = 'EventWeighted'
)
GO
這就是所謂的從這樣的存儲過程:
SELECT results.*
FROM PI.pipoint..pipoint2 points
CROSS APPLY dbo.fnGetResultsForTag(points.tag) AS results
WHERE points.tag LIKE @TagPattern
ORDER BY time ASC, tag ASC
的應用運算符的工作我n個以下方式產生用於FROM子句表源:針對left_table_source以產生行集的每一行
評估板right_table_source。
right_table_source中的值取決於left_table_source。 right_table_source可以用這種方式表示:TVF(left_table_source.row),其中TVF是一個表值函數。
通過執行UNION ALL操作,將right_table_source評估中每行生成的結果集與left_table_source組合在一起。
APPLY運算符的結果生成的列列表是來自left_table_source的列的集合,與來自right_table_source的列列表組合在一起。
這正是我想要的行爲。但這不是SQL Server實際做的。
實際上會發生什麼情況是,SQL Server查詢優化器試圖通過在WHERE子句中運行的遠程服務器上一個SELECT FROM PI.piarchive..picount
查詢,沒有的tag = @elapsedTimeTag
和filterexpr = <stuff>
表達式來優化TVF子查詢,然後做一個在SQL Server中加入以僅選擇指定標籤的數據。
不幸的是,這是不正確的優化。 picount表是包含數千個標籤的底層數據庫視圖。如果tag = @elapsedTimeTag
篩選條件未提供給遠程服務器,則查詢超時。並且filterexpr=<stuff>
條件需要與標記條件匹配相同的標記名,以獲得正確的答案。所以我真的需要爲左邊表中的每一行運行一個TVF遠程子查詢。
如何提示/強制SQL Server到實際上對CROSS APPLY的左側表格中的每一行運行表值函數的查詢一次,而不是當前正在執行的操作?
我試圖重構外部查詢首先明確選擇標籤列表,但它似乎並沒有幫助:
DECLARE @TagNames AS TABLE (tag NVARCHAR(50) NOT NULL)
INSERT INTO @TagNames
SELECT tag FROM PI.pipoint..pipoint2 WHERE tag LIKE @TagPattern
SELECT results.*
FROM @TagNames t
CROSS APPLY dbo.fnGetResultsForTag(t.tag) AS results
ORDER BY time ASC, tag ASC
你能發佈執行計劃嗎?您鏈接的文檔可能不適用於ITVF,因爲優化器可以「內聯」該函數 - 它可以內聯函數的主體並運行您的查詢,就像它是一個大選。這可能就是你所看到的這是因爲你的服務器上有一個查詢鏈接服務器數據的ITVF會更加複雜。當您直接在外部服務器實例上運行時,此查詢的行爲如何? –
你希望看到執行計劃的格式是什麼? – Hydrargyrum
如果我直接在外部服務器上運行TVF查詢,提供一個標籤名稱作爲參數,它就像我期望的那樣工作。我認爲外部服務器沒有實現CROSS APPLY,所以外部查詢不能直接運行。這部分必須在SQL Server中。 – Hydrargyrum