2 回答

TA貢獻(xiàn)1794條經(jīng)驗(yàn) 獲得超8個(gè)贊
這些差異可能很微妙,有時(shí)很重要,有時(shí)實(shí)際上根本不存在。
一般來說,準(zhǔn)備好的語句 1. 與服務(wù)器一起準(zhǔn)備(SQL 解析,生成執(zhí)行計(jì)劃等),2. 使用附加參數(shù)執(zhí)行,然后 3. 關(guān)閉。它可以讓你重用相同的 SQL,每次傳入不同的參數(shù),它可以幫助防止 SQL 注入,可以提供一些性能增強(qiáng)(驅(qū)動(dòng)程序/協(xié)議特定,YMMV)并防止重復(fù)步驟,如執(zhí)行計(jì)劃生成和 SQL 解析上面的準(zhǔn)備步驟。
對(duì)于編寫源代碼的人來說,準(zhǔn)備好的語句可能比連接字符串并將它們發(fā)送到數(shù)據(jù)庫服務(wù)器更方便。
該DB.Query()
方法將 SQL 作為字符串,以及零個(gè)或多個(gè)參數(shù)(如Exec()
, 或QueryRow()
)。沒有附加參數(shù)的 SQL 字符串將準(zhǔn)確查詢您編寫的內(nèi)容。但是,如果提供了一個(gè)帶有占位符和附加參數(shù)的 SQL 字符串,則會(huì)在后臺(tái)為您完成準(zhǔn)備好的語句。
該DB.Prepare()
方法顯式執(zhí)行一個(gè)準(zhǔn)備好的語句,然后您將參數(shù)傳遞給該語句,如:stmt.Exec(...args)
.
就兩者之間的差異以及為什么要使用其中之一而言,有幾件事值得考慮。
您可以DB.Query()
不帶參數(shù)使用。這可能非常有效,因?yàn)樗梢岳@過準(zhǔn)備好的語句必須經(jīng)過的準(zhǔn)備 --> 執(zhí)行 --> 關(guān)閉序列。
您還可以在查詢字符串中將其與其他參數(shù)和占位符一起使用,它會(huì)在我上面提到的封面下執(zhí)行準(zhǔn)備好的語句。這里的潛在問題是,當(dāng)您進(jìn)行大量查詢時(shí),每個(gè)查詢都會(huì)產(chǎn)生一個(gè)幕后準(zhǔn)備好的語句。由于涉及額外的步驟,因此每次執(zhí)行該查詢時(shí)它都會(huì)重新準(zhǔn)備、執(zhí)行和關(guān)閉,因此效率可能相當(dāng)?shù)汀?/p>
使用顯式準(zhǔn)備好的語句,您可以避免這種低效率,因?yàn)槟鷩L試重用之前準(zhǔn)備的 SQL,可能帶有不同的參數(shù)。
但這并不總是如您所料...由于由 db/sql 管理的底層連接池,您的“數(shù)據(jù)庫連接”是相當(dāng)虛擬的。該DB.Prepare()
方法將針對(duì)特定連接準(zhǔn)備語句,然后在執(zhí)行時(shí)嘗試取回相同的連接,但如果該連接不可用,它將簡單地抓取一個(gè)可用的連接并重新準(zhǔn)備并針對(duì)該連接執(zhí)行。如果您一遍又一遍地使用相同的準(zhǔn)備好的語句,那么您可能會(huì)在不知不覺中一遍又一遍地準(zhǔn)備它。當(dāng)您處理繁忙的交通時(shí),這顯然主要是暴露出來的。
所以很明顯,你在什么情況下使用取決于你的具體用例,但我希望上面的細(xì)節(jié)足以幫助你澄清,你可以在每種情況下做出最好的決定。
更新
鑒于 OP 中的更新,當(dāng)查詢只需要執(zhí)行一次時(shí)基本上沒有區(qū)別,因?yàn)閹в袇?shù)的查詢是在幕后作為準(zhǔn)備好的語句完成的。
使用直接方法,例如DB.Query()
及其類似物,而不是顯式使用準(zhǔn)備好的語句,因?yàn)樗鼤?huì)導(dǎo)致源代碼更簡單。
由于在這種情況下,出于安全原因使用準(zhǔn)備好的語句,因此可能值得努力通過其他方式處理安全問題并改用明文查詢,因?yàn)樗鼤?huì)提高性能。但是,除非有足夠的流量(或預(yù)計(jì)流量在未來會(huì)大幅增長)以減輕服務(wù)器上的負(fù)載,否則任何收益都可能無關(guān)緊要。再次歸結(jié)為現(xiàn)實(shí)世界的用例。
對(duì)于任何對(duì)準(zhǔn)備好的語句和直接明文查詢之間的差異的一些指標(biāo)感興趣的人,這里有一篇很好的文章(它也很好地解釋了上述大部分內(nèi)容)。

TA貢獻(xiàn)1871條經(jīng)驗(yàn) 獲得超13個(gè)贊
這在一定程度上取決于您使用的驅(qū)動(dòng)程序,以及您的數(shù)據(jù)庫軟件是否支持未準(zhǔn)備的查詢。
Prepare 連接到數(shù)據(jù)庫并創(chuàng)建一個(gè)準(zhǔn)備好的語句,綁定到該數(shù)據(jù)庫連接。執(zhí)行時(shí),它會(huì)檢查該連接是否仍然可用,如果不可用,則創(chuàng)建一個(gè)新連接,重新準(zhǔn)備函數(shù),然后運(yùn)行它。
編輯:注意,如果您一次只有一個(gè)例程連接到數(shù)據(jù)庫,并且您使用不同的參數(shù)一遍又一遍地運(yùn)行相同的查詢,那么 Prepare 可以更快,因?yàn)樗鼘⒉樵兇鎯?chǔ)在數(shù)據(jù)庫端。但是,其他例程的連接劫持否定了這一點(diǎn),如果您只使用一次查詢,則完全不會(huì)從 Prepare 中獲得任何好處。
查詢根據(jù)驅(qū)動(dòng)程序執(zhí)行兩件事之一。如果Conn
驅(qū)動(dòng)返回的類型Open()
也有Query()
方法,因此支持直接查詢,則sql.Query()
直接調(diào)用該方法,并返回其結(jié)果。如果Conn
沒有方法,則準(zhǔn)備一個(gè)語句,然后執(zhí)行它。Query()
sql.Query()
例如,pq
PostgreSQL (github.com/lib/pq) 的驅(qū)動(dòng)程序有一個(gè)Query()
方法。這個(gè)方法像sql
包一樣準(zhǔn)備和執(zhí)行,但也有一個(gè)替代方法:如果查詢沒有參數(shù),它使用simpleQuery
接口執(zhí)行,包說明這個(gè)接口比準(zhǔn)備和執(zhí)行周期快得多。
- 2 回答
- 0 關(guān)注
- 465 瀏覽
添加回答
舉報(bào)