亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Go 中通過語句或數據庫使用 QueryRow

在 Go 中通過語句或數據庫使用 QueryRow

Go
繁星點點滴滴 2022-05-18 14:20:43
下面的查詢執行方法在 DB 中發出完全相同的(3 個)查詢,這很好且易于理解 -見下文。但是,我想知道的是,就 Go 而言,兩者在內存、cpu、緩存、連接使用等方面是否存在真正的區別?查詢2020-02-22T12:29:23.858393Z 41 Prepare SELECT id, uuid, name FROM users WHERE id = ?2020-02-22T12:29:23.859601Z 41 Execute SELECT id, uuid, name FROM users WHERE id = 12020-02-22T12:29:23.861607Z 41 Close   stmt方法func Select1(query string, args ...interface{}) (*sql.Row, error) {    stmt, err := DB.Prepare(query)    if err != nil {        return nil, err    }    defer stmt.Close()    return stmt.QueryRow(args...), nil}func Select2(query string, args ...interface{}) *sql.Row {    return DB.QueryRow(query, args...)}
查看完整描述

2 回答

?
藍山帝景

TA貢獻1843條經驗 獲得超7個贊

除了@mkopriva 在關于客戶端的評論中所說的內容之外,使用準備好的語句還有服務器端的影響。

重要的是要注意 using*sql.DB使用連接池

DB 是代表零個或多個底層連接池的數據庫句柄

為什么這很重要?那么并發訪問可能會觸發多個物理連接。并且當使用準備好的語句時——它們應該被重用——只有在同一個數據庫會話(即連接)上使用時才有效。

連接池(使用*sql.DB)本質上不能保證這一點。因此,如果有 100 個并發查詢 - 理論上可能會生成 100 個并發數據庫連接 -不是一個 - 但在服務器端最多有 100 個準備好的語句。

您可以通過sql.DB.Conn()獲得與數據庫的單個連接,其中:

在同一個 Conn 上運行的查詢將在同一個數據庫會話中運行。

這意味著任何先前生成的準備好的語句都將獲得重用的好處(因為它們使用相同的“會話”)。

總之,權衡準備好的語句對客戶端服務器影響的好處,以及您是否真的通過并發使用獲得了這些好處。


查看完整回答
反對 回復 2022-05-18
?
MMTTMM

TA貢獻1869條經驗 獲得超4個贊

我花了更多時間進行測試和分析,所以這是我的發現 - 也證實了@mkopriva 的評論。

如果使用SELECT語句,無論是否使用查詢占位符,您都應該更喜歡使用DB.Query和/或DB.QueryRow而不是DB.Prepare&STMT.Exec組合。DB.Query當我檢查 MySQL 查詢日志時,它看起來就像DB.QueryRow 它們用于DB.Exec沒有參數占位符的查詢一樣。這意味著只有一個Query) 網絡往返而不是三個Prepare,ExecuteClose)!

那么為什么不直接使用DB.Exec呢?因為它用于不返回結果集的查詢。順便說一句,DB.Exec它直接釋放它的連接回池,但DB.Query它的連接保持在池之外,直到rows.Close()被調用。如果您忘記調用它,這可能會導致連接“泄漏”和連接不可用。因此,從技術上講,DB.Query如果您沒有正確地做事,就會有其自身的風險。

最后要注意的是,如果您的INSERT,UPDATEDELETEquery 參數沒有 SQL 注入,那么請使用DB.Execelse 來DB.Prepare代替。對于手動準備查詢參數,您可以使用fmt.Sprintf()函數。


查看完整回答
反對 回復 2022-05-18
  • 2 回答
  • 0 關注
  • 473 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號