2013-11-27 46 views
1

我知道已經有很多關於存儲過程和準備好的SQL語句的問題,但是我想找出一些不同的東西 - 如果一個過程中的預處理語句對這個存儲過程的性能有所貢獻,這意味着使它更好。存儲過程中準備好的SQL語句是否使性能更好?

我有這個問題,因爲我在搜索這些2技能的介紹時被告知以下幾點。

  • 存儲過程將存儲和編譯一系列的語句在 分貝,這將減少傳輸&編譯的開銷。
  • 準備語句將被編譯和緩存在db中,用於多個
    訪問,從而導致更少的開銷。

我對這些'編譯','存儲'和'開銷'感到困惑 - 有點抽象。

我使用準備語句來避免重新解析,如果它會被頻繁調用。 但是,我應該在程序中使用預處理語句(緩存&編譯)嗎?由於我的程序已經被存儲和編譯爲數據庫,所以在內部準備好似乎沒有意義。(編譯什麼編制?)

編輯與示例代碼:

Create or Replace procedure MY_PROCEDURE 
Begin 
    //totally meaningless here? 
    declare sqlStmt varchar(300); 
    declare stmt statement; 

    set sqlStmt='update MY_TABLE set NY_COLUMN=? where NY_COLUMN=?'; 
    prepare stmt from sqlStmt; 
    execute stmt using 2,1 
    execute stmt using 4,3 
     .............. 
END 

是在上面的一個比下面的更好,因爲它只分析語句一次?或者相同,因爲程序中的語句將被預編譯。

Create or Replace procedure MY_PROCEDURE 
Begin 
    update MY_TABLE set NY_COLUMN=2 where NY_COLUMN=1; 
    update MY_TABLE set NY_COLUMN=4 where NY_COLUMN=3; 
     .............. 
END 
+0

個人,我不認爲什麼數據庫事宜...指出,如果我錯了 –

+1

什麼**具體產品**你正在使用**最有可能**影響可以說!這些東西總是**高度供應商特定**,並且SQL Server的某些內容可能不適用於DB2或Oracle **(反之亦然)! –

+0

@marc_s我同意,比如我的示例代碼只能運行在db2中。但我的問題是各種通用的,因爲許多流行的數據庫支持臨時SQL和程序。我猜不同的分貝處理的關鍵不會有太大的變化。如果我的問題的答案確實取決於所用的具體產品,例如不需要在SQL Server中準備,但它在DB2中有效,那麼我想知道相似性和差異。這些會幫助我。無論如何,我還沒有完成你之前發佈的答案。至少在閱讀時,我真的認爲它有幫助 - '這方面的一般信息仍然相關'。 –

回答

2

在DB2中實際上可能是相反的。 SQL例程中的語句在編譯例程時準備好。像在你的例子中那樣,動態SQL語句是在例程運行時準備的。

因此,動態語句的準備工作將考慮最新的表和索引統計信息以及其他編譯環境設置(例如隔離級別),而靜態語句將使用在例程編譯期間生效的統計信息或最新的綁定。

如果您想要穩定的執行計劃,請使用靜態SQL。如果您的統計信息頻繁更改,則可能需要使用動態SQL(或確保相應地重新綁定您的例程的包)。

相同的邏輯適用於Oracle PL/SQL例程,儘管重新編譯靜態SQL的方式不同 - 您需要使相應的例程無效。

+0

@OGHaza - 什麼部分讓你感到困惑?創建例程時,靜態SQL將被準備一次;每次在新會話中調用例程時都會準備動態SQL。即使您在同一個會話中調用它,仍然會有一些開銷,因爲編譯器需要查詢語句高速緩存中的每個動態語句以確定它是否已經存在。 – mustaccio

+0

因此,每個靜態SQL也是在一個過程/例程中準備的,我不需要將它們更改爲動態SQL併爲性能做好準備。如果我這樣做,將導致每次調用動態SQL時進行準備,這會導致更多的開銷來調用該過程。我對嗎? –

+0

讓我澄清更多。我準備一個聲明只是爲了避免重新解析,如果它被稱爲多次。但是由於一個過程會在編譯時解析所有靜態語句,所以在調用過程時不會有任何消耗語句的開銷。無論在我的程序中聲明重複多少次,準備本聲明都不會影響實際運行時間。請指出,如果我錯了 –

2

當你第一次運行存儲過程的數據庫引擎解析過程和作品進行執行時,它使用最優查詢計劃 - 它然後存儲這個查詢計劃,以便每次運行沒有關係」的程序不得不重新計算它。

你可以在Management Studio中看到你自己。如果你CREATEALTER有問題的存儲過程,然後打開一個新的查詢和使用:

SET STATISTICS TIME ON 

在同一個查詢窗口運行存儲過程。在結果的信息選項卡中的第一條消息會是這樣的:

SQL Server parse and compile time: 
CPU time = 1038 ms, elapsed time = 1058 ms. 

這是開銷,再次執行查詢,你會看到,分析和編譯現在時間是0

當你準備了一個代碼聲明,你可以利用同樣的好處。如果查詢是'SELECT * FROM table WHERE @var = '+$var,則每次運行該查詢時,SQL Server都必須對其進行解析並計算最佳執行計劃。如果您使用預準備語句SELECT * FROM table WHERE ?,則SQL Server將在您首次運行準備好的語句時計算最佳執行計劃,並且從此可以像存儲過程一樣重用執行計劃。如果執行的語句是'EXEC dbo.myProc @var = '+$var,那麼SQL Server每次仍然必須解析此語句,因此仍應使用預準備語句。

您不需要準備在存儲過程中編寫的語句,因爲它們已經按上面所示進行了編譯 - 它們本身就是準備好的語句。

在您應該意識到使用存儲過程和預處理語句時,事情是參數嗅探

SQL Server計算並存儲所使用的第一個變量的最佳執行計劃,如果您碰巧在第一次運行時執行帶有一些不尋常變量的存儲過程,則存儲的執行計劃可能對於各種變量而言是完全次優的通常使用。

如果您發現可以從Management Studio執行存儲過程,並且需要執行2秒,但在應用程序中執行相同的操作需要20秒,這可能是參數嗅探的結果。

+0

bah,這是在一分鐘前標記爲「sql-server」的嗎?在這個更一般的信息仍然是相關的,所以將它留在這裏無論如何,只是忽略對管理工作室的引用... – OGHaza

+0

是的,實際上我不認爲我使用什麼樣的數據庫會影響我的問題很多。幸運在之前標記錯誤的標籤或我無法閱讀你的答案 –

相關問題