2 回答

TA貢獻1843條經驗 獲得超7個贊
除了@mkopriva 在關于客戶端的評論中所說的內容之外,使用準備好的語句還有服務器端的影響。
重要的是要注意 using*sql.DB
使用連接池:
DB 是代表零個或多個底層連接池的數據庫句柄
為什么這很重要?那么并發訪問可能會觸發多個物理連接。并且當使用準備好的語句時——它們應該被重用——只有在同一個數據庫會話(即連接)上使用時才有效。
連接池(使用*sql.DB
)本質上不能保證這一點。因此,如果有 100 個并發查詢 - 理論上可能會生成 100 個并發數據庫連接 -不是一個 - 但在服務器端最多有 100 個準備好的語句。
您可以通過sql.DB.Conn()獲得與數據庫的單個連接,其中:
在同一個 Conn 上運行的查詢將在同一個數據庫會話中運行。
這意味著任何先前生成的準備好的語句都將獲得重用的好處(因為它們使用相同的“會話”)。
總之,權衡準備好的語句對客戶端和服務器影響的好處,以及您是否真的通過并發使用獲得了這些好處。

TA貢獻1869條經驗 獲得超4個贊
我花了更多時間進行測試和分析,所以這是我的發現 - 也證實了@mkopriva 的評論。
如果使用SELECT
語句,無論是否使用查詢占位符,您都應該更喜歡使用DB.Query
和/或DB.QueryRow
而不是DB.Prepare
&STMT.Exec
組合。DB.Query
當我檢查 MySQL 查詢日志時,它看起來就像DB.QueryRow
它們用于DB.Exec
沒有參數占位符的查詢一樣。這意味著只有一個( Query
) 網絡往返而不是三個( Prepare
,Execute
和Close
)!
那么為什么不直接使用DB.Exec
呢?因為它用于不返回結果集的查詢。順便說一句,DB.Exec
它直接釋放它的連接回池,但DB.Query
它的連接保持在池之外,直到rows.Close()
被調用。如果您忘記調用它,這可能會導致連接“泄漏”和連接不可用。因此,從技術上講,DB.Query
如果您沒有正確地做事,就會有其自身的風險。
最后要注意的是,如果您的INSERT
,UPDATE
和DELETE
query 參數沒有 SQL 注入,那么請使用DB.Exec
else 來DB.Prepare
代替。對于手動準備查詢參數,您可以使用fmt.Sprintf()函數。
- 2 回答
- 0 關注
- 473 瀏覽
添加回答
舉報