Go sql - 预处理语句作用域

Go sql - prepared statement scope

我正在使用 Go (1.6.x) sql 包和 PostGres (9.4) 构建一个 API。我准备好的陈述应该有应用或请求范围吗?阅读文档后,在应用程序级别确定它们的范围似乎更有效,以减少准备阶段的数量。但是,也许还有其他的考虑,准备好的语句并不是为了活那么久而设计的?

准备好的语句使您可以执行重复的 SQL 命令,例如,这些命令可能仅在参数值上有所不同。

它们并不意味着 "long" 存在,因为准备好的语句可能(如果从事务中调用它们会这样做)保留活动的数据库连接("long" 意味着它们不被使用时;它是多次重复执行准备好的语句非常好,即使这会花费很长时间)。连接是一种昂贵的资源,只应在需要时保持。只需创建一堆准备好的语句而不关闭它们,您就可以 运行 退出活动/允许的连接,然后阻止与数据库服务器的进一步通信。

如果要在一个 (HTTP) 请求中多次执行具有不同参数的相同 insertupdateselect 语句,请使用准备好的语句。不要使用准备好的语句来延长 (HTTP) 请求。

在某些驱动程序实现和数据库服务器中,准备好的语句也可能涉及在数据库服务器本身(而不是在 Go 应用程序中)上分配的资源。例如,准备好的语句可能在数据库服务器上预编译,服务器可能会准备查询执行计划,为其分配某些资源(如内存)。这些可能会永久保留,直到准备好的语句关闭。

有一篇文章(由 Myles McDonnell 在下面的评论中发表)详细介绍了 Prepared Statements 在 Go 中的实现细节。它提到如果准备好的语句不是从事务中创建的,它们会将连接释放回连接池,但在需要时,它们会尝试重用它们准备好的语句(因为如果数据库服务器帮助/也发挥积极作用在准备好的语句中,它绑定到服务器端的连接)。如果没有,他们将在新连接上重新准备它们(导致不希望的性能开销)。

总而言之,您所描述的是一个工作模型,如果您在许多后续请求中需要/执行的准备好的语句数量很少,它们可能意味着更短的响应时间。但这也意味着另一方面,在长 运行 上,它们可能会导致您所有准备好的语句都将在池的所有连接上准备。确定这在您的情况下是否可以接受。

一般来说,应该避免这种情况(并且在 HTTP 请求结束之前关闭准备好的语句),但是如果您只有少数几个,并且在许多请求中确实需要它们,您可以移动它们超出了请求范围。