SQL Server 是否只在 SELECT 列表中執行一次計算?
舉個例子:
SELECT <CalculationA> As ColA, <CalculationB> As ColB, <CalculationA> + <CalculationB> As ColC FROM TableA
CalculationA 和 CalculationB 會分別計算兩次嗎?
或者優化器是否足夠聰明,可以計算一次並使用兩次結果?
我想自己進行測試以查看結果,但是,我不確定如何檢查這樣的事情。
我的假設是它會執行兩次計算。
在哪種情況下,根據所涉及的計算,使用派生表或嵌套視圖會更好嗎?考慮以下:
SELECT TableB.ColA, TableB.ColB, TableB.ColA + TableB.ColB AS ColC, FROM( SELECT <CalculationA> As ColA, <CalculationB> As ColB FROM TableA ) As TableB
在這種情況下,我希望計算只執行一次?
請問有人可以證實或反駁我的假設嗎?或者指導我如何為自己測試這樣的東西?
謝謝。
您需要的大部分資訊都將包含在執行計劃(和計劃 XML)中。
接受這個查詢:
SELECT COUNT(val) As ColA, COUNT(val2) As ColB, COUNT(val) + COUNT(val2) As ColC FROM dbo.TableA;
執行計劃 *(用sentryone plan explorer打開)*顯示了它經歷了哪些步驟:
使用流聚合聚合EXPR1005和EXPR1006的值
如果我們想知道這些是什麼,我們可以從查詢計劃 XML 中獲取有關這些表達式的確切資訊:
<ColumnReference Column="Expr1005" /> <ScalarOperator ScalarString="COUNT([Database].[dbo].[TableA].[val])"> <Aggregate AggType="COUNT_BIG" Distinct="false">
使用第一個計算標量計算
ColA & ColB
:最後一個計算標量是一個簡單的加法:
這是在數據流動時讀取它,理論上如果遍歷邏輯執行,您應該從左到右讀取它。
在這種情況下,
EXPR1004
呼叫其他表達式EXPR1002
&EXPR1003
。反過來,這些正在呼叫EXPR1005
&EXPR1006
。CalculationA 和 CalculationB 會分別計算兩次嗎?或者優化器是否足夠聰明,可以計算一次並使用兩次結果?
先前的測試表明,在這種情況下
ColC
,簡化為定義為ColA
&的計算的添加ColB
。結果,
ColA
&ColB
只計算一次。按 200 個不同的值分組
如果我們按 200 個不同的值 (val3) 分組,則顯示相同:
SET STATISTICS IO, TIME ON; SELECT SUM(val) As ColA, SUM(val2) As ColB, SUM(val) + SUM(val2) As ColC FROM dbo.TableA GROUP BY val3;
匯總到這 200 個不同的值
val3
對 val 和 val2 進行求和,然後將它們加到 ColC 中:
即使我們對除一個非唯一值之外的所有值進行分組,計算標量也應該看到相同的加法。
向 ColA 和 ColB 添加函式
即使我們將查詢更改為:
SET STATISTICS IO, TIME ON; SELECT ABS(SUM(val)) As ColA, ABS(SUM(val2)) As ColB, SUM(val) + SUM(val2) As ColC FROM dbo.TableA
聚合仍然不會計算兩次,我們只是將
ABS()
函式添加到聚合的結果集中,即一行:當然,執行
SUM(ABS(ColA)
&SUM(ABS(ColB))
會使優化器無法使用相同的表達式來計算ColC
。如果您想在發生這種情況時更深入地了解,我會向您推薦Paul White 的Query Optimizer Deep Dive - 第 1 部分(直到第 4 部分)。
深入了解查詢執行階段的另一種方法是添加以下提示:
OPTION ( RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8605 );
這將公開優化器創建的輸入樹。
然後將要獲取的兩個先前計算值相加
ColC
轉換為:AncOp_PrjEl COL: Expr1004 ScaOp_Arithmetic x_aopAdd ScaOp_Identifier COL: Expr1002 ScaOp_Identifier COL: Expr1003
甚至在簡化階段發生之前,輸入樹中就已經存在此資訊,這表明優化器立即知道它不必執行相同的計算兩次。