2016-08-20 57 views
1

流行測驗,SQL Server能手:可以在單個查詢中有效完成「常量」查找嗎?

下面student子查詢將被執行多少次? (假設有在something至少十行):

SELECT TOP 10 a, b 
    , (SELECT type_id 
      FROM type 
     WHERE type_code = 'student') student 
    FROM something 

如果說1,然後像我一樣,你承擔的SQL Server將認識到student值作爲一個不變的標量。

遺憾的是,答案是10:

Execution plan for inline select and CTE versions

Index seek details for inline and CTE execution plan

我知道,我將使用一個CTE!

WITH codes (student) AS (
    SELECT (SELECT type_id 
       FROM type 
      WHERE type_code = 'student') 
) 
SELECT TOP 10 a, b 
    , student 
    FROM something 
CROSS JOIN codes 

結果是完全一樣的。

當然,我可以先捕獲標給一個變量獲得所需的效率:

DECLARE @Student tinyint 
SELECT @Student = type_id 
    FROM type 
WHERE type_code = 'student' 

SELECT TOP 10 a, b 
    , @Student student 
    FROM something 

這隻做一求,並增加了無以主查詢計劃:

Execution plan for scalar pre-stored in variable

除了更詳細的內容,如果你正在定義一個內聯表值函數,這意味着你還必須寫出一個隱含的返回模式,這是一個痛苦(並且爲錯誤添加了一個向量)。

有沒有什麼辦法可以寫一個只運行子查詢的查詢?

+0

出於興趣,是它的TOP 10是造成這種現象?而且,如果是這樣,如果將TOP 10放入子查詢中,會發生什麼情況,然後使用不同的選項來「加入」/「附加」您的標量常量? – MatBailie

+0

@MatBailie,*很有趣。 「TOP 0」只是爲了「簡化」這個例子,但它確實影響了結果。當我刪除它時,我確實會得到一個搜索,但它也增加了一個「表假脫機」,每行完成一次,總成本爲90%。所以很高興知道這會帶來意想不到的效果,但從接受的答案中得出的建議仍然比原來更簡單和更高效 - 按照我預期的方式行事。當「MWE」不夠「M」時,會發生這種情況! – harpo

回答

2

對於此查詢:

SELECT TOP 10 a, b, 
     (SELECT type_id FROM type WHERE type_code = 'student' 
    ) as student 
FROM something; 

你想在type(type_code, type_id)的索引。

如果移動子查詢到FROM子句您可能會發現這個更高效:

SELECT TOP 10 a, b, 
     t.type_id 
FROM something s CROSS JOIN 
    (SELECT type_id FROM type WHERE type_code = 'student' 
    ) t 

甚至:

SELECT TOP 10 s.a, s.b, t.type_id 
FROM something s JOIN 
    type t 
    ON t.type_code = 'student'; 
+0

問題不在於沒有使用索引(它是) - 它是在每一行*上使用*來查找相同的值。我對'type_code'有一個'UNIQUE'約束,它隱式地創建了一個索引,該索引正在被計劃使用。不過,我嘗試了你的建議,並得到了同樣的結果。 – harpo

+0

@harpo。 。 。對。正確的解決方案是將子查詢移到「FROM」。 –

+0

謝謝,戈登!這兩者都會導致在類型表上進行一次查找。我期望'CROSS JOIN'在語義上與我的CTE版本沒有區別。我在那裏做了標量,因爲實際上有多個代碼查找。無論如何,再次感謝您的建議! – harpo

相關問題