2014-11-25 42 views
1

我注意到下面的時間是32秒在SQL Server(2008 R2)查詢減慢條件下IF

IF ((SELECT COUNT(*) FROM view1) != 0) 
    OR ((SELECT COUNT(*) FROM view2) != 0) 
    OR ((SELECT COUNT(*) FROM view3) != 0) 
    OR ((SELECT COUNT(*) FROM view4) != 0) 
    OR ((SELECT COUNT(*) FROM view5) != 0) 
    OR ((SELECT COUNT(*) FROM view6) != 0) 
     PRINT 'HI' 

運行然而,只有以下了4秒

SELECT 
    (SELECT COUNT(*) FROM view1) 
    , (SELECT COUNT(*) FROM view2) 
    , (SELECT COUNT(*) FROM view3) 
    , (SELECT COUNT(*) FROM view4) 
    , (SELECT COUNT(*) FROM view5) 
    , (SELECT COUNT(*) FROM viwe6) 

我有設法通過執行SELECT COUNT(1)... + SELECT ...!= 0來優化條件,這樣它需要4秒,但是查看執行計劃還沒有產生任何特別顯着的結果。沒有太多的機會用google搜索詞或者。

有人可以分享一下SQL Server優化器可能在背後做什麼嗎?

編輯:如果EXISTS嘗試了38秒。

IF EXISTS ((SELECT 1 FROM view1) 
    UNION (SELECT 1 FROM view2) 
    UNION (SELECT 1 FROM view3) 
    UNION (SELECT 1 FROM view4) 
    UNION (SELECT 1 FROM view5) 
    UNION (SELECT 1 FROM view6)) 
     PRINT 'HI' 

EDIT2:目前的第5種方法。

IF (SELECT COUNT(1) FROM view1) 
    + (SELECT COUNT(1) FROM view2) 
    + (SELECT COUNT(1) FROM view3) 
    + (SELECT COUNT(1) FROM view4) 
    + (SELECT COUNT(1) FROM view5) 
    + (SELECT COUNT(1) FROM viwe6) != 0 
     PRINT 'HI' 

EDIT3:比較20page大小的查詢計劃之後 - 它出現的加速主要是由於基本觀點都做了局部聚集的加入,而不是做連接,然後彙總之前。

+0

你做EXISTS獲得更好的性能(SELECT 1 FROM廠景),因爲這會停止尋找它發現一排後,而不是統計所有行。 – Brandon 2014-11-25 01:31:33

+0

我確實嘗試了EXISTS。但它也花了大約38秒。我會把我在編輯中嘗試的東西放進去。 – 2014-11-25 01:43:45

+0

一個快速的想法把計數結果放到變量中,然後使用IF條件 – 2014-11-25 06:55:51

回答

0

下面的代碼需要多長時間才能運行?如果將查詢轉換爲EXISTS,則需要避免使用UNION,因爲在您的示例中,每個視圖的每行都會強制SQL爲UNION,然後查看是否存在元素。下面的答案將有機會盡快停止。

IF EXISTS(SELECT 1 FROM view1) 
    OR EXISTS(SELECT 1 FROM view2) 
    OR EXISTS(SELECT 1 FROM view3) 
    OR EXISTS(SELECT 1 FROM view4) 
    OR EXISTS(SELECT 1 FROM view5) 
    OR EXISTS(SELECT 1 FROM view6) 
    PRINT 'HI' 

這裏是用一個頂部的另一種方法存在 - 也許是基於對爲何多EXISTS被執行,所以慢慢地你應該更好的提供解釋。

IF EXISTS (
    SELECT TOP (1) 1 FROM view1 
    UNION ALL SELECT TOP (1) 1 FROM view2 
    UNION ALL SELECT TOP (1) 1 FROM view3 
    UNION ALL SELECT TOP (1) 1 FROM view4 
    UNION ALL SELECT TOP (1) 1 FROM view5 
    UNION ALL SELECT TOP (1) 1 FROM view6 
    ) 
    PRINT 'Hi' 

至於在引擎蓋下你的問題,下面的網址具有良好的書面記錄: http://sqlserverplanet.com/tsql/comparing-exists-vs-left-join-where-not-null

基本上,它描述了使用EXISTS時,單語句與不創建一個工作表,以便多個EXISTS,性能可能會變慢,就像你的情況一樣。

+0

沒多少運氣,花了29秒。 我推測問題不是'退出'儘快 - 而是由於if語句導致執行計劃不佳的底層SQL優化引擎。我仍然在質疑爲什麼以及它可能在底層做什麼。 – 2014-11-25 06:47:21

+0

你可以運行備用查詢嗎?我添加了一些信息和博客文章的鏈接,說明爲什麼像這樣的多個EXISTS在某些情況下可能會變慢。 – 2014-11-25 13:02:21

+0

有趣的是執行計劃是用於上述兩種查詢的相同,但假想的單個EXISTS應該更加優化 – 2014-11-25 13:03:12

0

使用TOP 1語句:

例如:

DECLARE @CONTROL INT; 
WITH CTE AS (
SELECT TOP 1 col FROM view1 
UNION ALL 
SELECT TOP 1 col FROM view2 
UNION ALL 
SELECT TOP 1 col FROM view3 
UNION ALL 
SELECT TOP 1 col FROM view4 
UNION ALL 
SELECT TOP 1 col FROM view5 
UNION ALL 
SELECT TOP 1 col FROM view6) 

SELECT @CONTROL = COUNT(col) FROM CTE 

IF @CONTROL != 0 
PRINT 'HI'