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 关注
- 393 浏览
添加回答
举报