2013-03-15 49 views
6

我有一段動態的SQL。大約需要4分鐘。如果我改用SQL的輸出並運行它,則需要大約20秒。爲何差異?我知道在動態版本中構建SQL需要一定的時間,但我無法想象它的成本太高。動態SQL比硬編碼的等效時間長得多

任何人有任何想法?這兩個查詢應該是相同的,所以我懷疑查詢計劃緩存有點奇怪,但實際上並沒有太多想法。

編輯: 澄清我的意思是通過輸出。

在動態SQL中的最後一行是

EXEC sp_executesql @myQuery, 
    N'@var1 INT, 
    @var2 INT, 
    @var2 INT', 
    @var1, 
    @var2, 
    @var3 

我把更改爲MyQuery的價值,並把它放在自己的SQL文件。運行時間爲20秒,而使用execute的動態運行需要4分鐘。

編輯2 我刪除了參數。我得到了有趣的結果。動態SQL語句看到了性能改進。硬編碼版本遭遇了巨大的性能影響。現在兩人差不多。

+9

請張貼您的代碼。 – Taryn 2013-03-15 19:04:39

+0

你可以顯示你的代碼嗎? – 2013-03-15 19:05:53

+0

您應該添加更多信息,但如果硬編碼速度更快,那麼您肯定是在做錯事。 – TFennis 2013-03-15 19:06:51

回答

6

我打算假設您正在使用Microsoft SQL Server(您只標記了您的問題「sql」)。

有些情況下,不同的參數值可能導致不同的優化計劃。然後,該優化計劃被緩存,並在下一次使用不同參數值執行查詢時使用。但優化計劃並不是後續參數值的最佳計劃。

這裏有一個關於這個問題和一些解決方法的文章: https://www.simple-talk.com/sql/t-sql-programming/parameter-sniffing/

所以,是的 - 有某些情況下,使用參數化查詢可能會導致性能不佳相比,運行同樣的查詢,而參數化。

如果您無權發佈您的代碼,我們無法知道這是否適用於您的情況。

我尊重你不能那樣做 - 通過張貼到StackOverflow,you implicitly license your code and/or words with a Creative Commons license。但分享您的僱主擁有的代碼是不合適的,除非他們同意。

+0

OP有oppisite問題;沒有參數化的查詢運行速度比使用參數化的查詢慢得多。 – 2013-03-15 19:24:42

+0

@PieterGeerkens,這不是我讀過OP描述的問題的方式。 – 2013-03-15 19:25:24

+0

無論哪種方式參數化與不會導致不同的查詢計劃。而不同的查詢計劃會導致不同的運行時間。 – 2013-03-15 19:36:13

4

如果您使用SQL Server 2008或更高版本,使用未知的查詢提示將優化。以下內容添加到您的動態查詢的末尾:

OPTION (OPTIMIZE FOR (@var1 UNKNOWN, @var2 UNKNOWN, @var3 UNKNOWN)) 

實驗用或縮小三個輸入@ VAR1,@ VAR2和@ VAR3改變。是的,如果查詢優化器試圖對某些真正特定的事情使用統計信息,那麼它確實可能非常昂貴。如果一個或多個變量具有相當的可預測性,那麼優化特定值並優化剩餘的未知值。查看此鏈接瞭解更多詳情。

https://blogs.msdn.microsoft.com/sqlprogrammability/2008/11/26/optimize-for-unknown-a-little-known-sql-server-2008-feature/

需要明確的是,這可能是一個參數作爲由ninjaPixel上面所指出的嗅探問題。與重新編譯每個查詢相比,OPTIMIZE FOR UNKNOWN可以爲您提供更好的結果,因爲查詢優化器依賴統計信息進行編譯。

+0

謝謝。最初,我打算給予忍者像素賞金,但這個答案更好。 – 2017-01-01 14:05:13

+0

很高興我能幫忙 – quest4truth 2017-01-04 17:10:22

2

爲您的動態查詢添加評論。 放入變量的值評論@ VAR1,@ VAR2,@ VAR3等

它看起來像:

EXEC sp_executesql @myQuery, 
    /* var1Value, var2Value, var3Value */  
    N'@var1 INT, 
    @var2 INT, 
    @var2 INT', 
    @var1, 
    @var2, 
    @var3 

因此,執行計劃將重新編譯只不同的值。