Go SQL 库中的 Query、Exec 和 Prepare 使用对比(附网络抓包)

Go

Go 附带的 database/sql 库可以与任何关系数据库进行对话. 为了抽象链接到数据库以及管理连接池的一些底层复杂性, 暴露的 APIs 比实际预期要多一点. 最终导致了一些关于如何使用这些 APIs 的想象.

因此, 我将尝试分析一下使用之前已知的主要 API 的行为.

我在主机的一个虚拟机 (ubuntu) 和一个 mysql 服务器上运行的 Go 应用程序进行了实验.

Query tried: insert into items (name, price, description) values (‘brownie’,240,’sizzling’)

查询

每当我们进行 select 时都应该是始终使用 db.Query, 并且我们绝不应该护理 Query 返回的rows, 而应对其进行迭代 (否则我们会泄露数据库链接)

执行 Query(query) 将不使用准备好的语句 (可参阅下面的 wireshark 捕获内容)

  • 注意从客户端到服务器仅发送了 1 个 TCP 请求 (减去登录)
  • 当迭代返回的 rows 时链接将自动释放回到池中, 或则我们可以在完成之后显式调用 rows.Close()
  • 用法 — db.Query(“insert into items (name, price, description) values(‘brownie’, 240, ‘sizzling’)”)

Go

查看 wireshark 捕获 (query)

执行 Query(queryTemplate, params) 将在幕后 使用准备好的语句

  • 注意从客户端向服务器发送了 3 个 TCP 请求 (减去登录)
  • 当迭代完返回的 rows 时, 链接将自动释放回到池中, 或者我们可以在完成之后显式调用 rows.Close().
  • 用法 — db.Query(“insert into items (name, price, description) values(?,?,?)”, “brownie”, 240, “sizzling”)

Go

Query(query, params) 的 wireshark 捕获

Exec

每当我们想要执行 insertupdatedelete 时都应该始终使用 db.Exec.

执行 Exec(query) 不会使用预备语句, 因此对 SQL Server 的 TCP 调用更少

  • 注意从客户端到服务器仅发送了 1 个 TCP 请求 (减去登录)
  • 自动释放链接回到池.
  • 用法 — db.Exec(“insert into items (name, price, description) values(‘brownie’, 240, ‘sizzling’)”)

Go

Exec(query) 的 wireshark 捕获

执行 Exec(queryTemplate, params) 将在幕后使用预备语句, 因此对 SQL Server 的 TCP 调用会多一些.

  • 注意从客户端向服务器发送了 3 个 TCP 请求 (减去登录)
  • 释放链接自动回到池.
  • 用法 — db.Exec(“insert into items (name, price, description) values(?,?,?)”, “brownie”, 240, “sizzling”)

Go

Exec(query, params) 的 wireshark 捕获

Prepare

仅当我们的程序要在开始时准备一次并在程序执行期间执行 N 次时, 才应使用此方法.

  • 注意有从客户端到服务端发送了 2 个 TCP 请求 (不算登录)
  • 当我们不需要预备语句时我们需要显式关闭语句. 否则, 我们将无法释放客户端和服务器上分配的资源!
  • 用法 — stmt.Exec(“insert into items (name, price, description) values(?,?,?)”, “brownie”, 240, “sizzling”)

Go

Prepare(query) 的 wireshark 捕获

结论

第一次使用 sql 包时, 我们遇到的主要困惑之一是, 即使我们没有明确指示这样做, 我们也不知道其在幕后创建了预备语句.

希望上述内容可以阐述清楚, 我们应该何时使用预备语句以及如何规避它们.
Hopefully the points above clarify, when are prepared statements invoked and how we can avoid them.

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/@alok.sinha.nov/query...

译文地址:https://learnku.com/go/t/49695

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!