2009-12-05 45 views
6

爲什麼使用參數化查詢到的數據插入表:爲什麼使用參數化查詢將數據插入到不是追加值的查詢字符串更快的表?

不是追加值的查詢字符串更快
string queryString = "insert into product(id, name) values (@id, @name)"; 

string queryString = "insert into product(id, name) values (" + _id + ", " + _name + ")"; 

當我在循環中使用該命令來插入10K行時,參數化查詢比另一個快一個數量級。

我知道一個參數化查詢具有安全性和可維護性的好處,並且它是推薦的使用方式,但是現在我對解釋爲什麼它會更快?

+4

不要的問題,而是享受,很少沒有任何事情最終會被更安全,更快捷! :) – Phil 2009-12-05 10:38:59

+0

你正在使用哪個數據庫? – RickNZ 2009-12-05 10:39:24

回答

8

通常,執行SQL查詢的最昂貴的部分是構建執行計劃 - 確定哪些表將被需要,確定最佳索引(如果有的話)等。您可以將其視爲「編譯」查詢,如果你喜歡。

當您使用參數化查詢時,您可以準備一次,然後插入不同的目標值。由於對不同數據的操作是相同的,所以不需要每次重建執行計劃。爲了擴展「編譯」隱喻,這就像重新運行具有不同配置文件的相同程序。

但是,當您附加值時,您將它們硬編碼到查詢中,因此每次都需要重新準備它,並且會產生爲每次迭代構建新執行計劃的成本。再次用「編譯」隱喻,這就像一個C程序,它的所有配置都是硬編碼的 - 改變一個設置,你必須重新編譯整個事物。

(可以運行在做大量插入時更新索引到其他主要成本。如果你的表是索引的,你可能會想嘗試將其關閉,這樣做你的插入,然後再打開,因此只有把他們被重新索引一次,而不是每行添加後。)

+0

構建執行計劃是僅在某些有限條件下執行SQL查詢的最昂貴的部分 - 絕對不是任何一般意義上的。 – RickNZ 2009-12-05 11:54:38

+0

有關這些條件有限的文檔,是否有鏈接?無可否認,我的確重複了我所聽到的,因爲它看起來似乎是合理的,但從來沒有試圖以查詢運行查詢所耗費的時間爲基準的細分,所以我有興趣瞭解實際情況。 (另外,OP表示,他看到參數化版本的運行時間減少了一個數量級,這表明,在這種情況下,準備查詢*是操作中最昂貴的部分。) – 2009-12-06 09:18:37

+0

查詢並不少見花一分鐘或更長的時間跑步;一些查詢可能需要24小時+。彙編通常需要很長時間。當然,如果編譯後的查詢以毫秒爲單位執行,那麼編譯可能會佔總執行時間的很大一部分,但在一般情況下,您的答案肯定不是這樣。 – RickNZ 2009-12-09 12:28:20

4

根據您正在使用的數據庫,通常的原因是因爲參數化查詢只需要進行一次編譯,動態查詢版本重新編譯每次使用。

+0

在Oracle上這種情況從未出現過,SQL Server自從v2005以來通過使用'sp_executesql'最終支持緩存的動態查詢計劃:http://www.sommarskog.se/dynamic_sql.html#queryplans – 2009-12-05 19:16:11

+0

動態SQL的自動查詢計劃緩存在SQL Server中只能使用單個參數(自動參數化);除此之外的差異被視爲計劃緩存的關鍵部分。 – RickNZ 2009-12-06 02:51:41

5

簡單。即使在查詢執行開始之前,解析並準備查詢的執行計劃也需要很長時間。

當您將參數作爲文本附加到查詢中時,每個查詢都不同,因此數據庫需要解析它並準備執行計劃。

當您使用參數時,您會多次發送相同的查詢(使用不同的數據),並且DB可以簡單地重複使用早期調用的執行計劃。

在這簡單的查詢之間的文本比較大多數的情況。 例如,在MS SQL Server的它足以改變一個字母的情況下,或在查詢的末尾添加一個空格,迫使DB重新執行計劃。

0

我打賭它不會更快,如果你使用多個值
你可以做到高達1000

string queryString = "insert into product(id, name) values " + 
" (" + _id + ", " + _name + ")" + 
" , (" + _id1 + ", " + _name1 + ")" + 
" , (" + _id2 + ", " + _name2 + ")"; 
相關問題