2016-07-15 200 views
1

我正在用Go(1.6.x)sql包与PostGres(9.4)一起构建一个API。我的预备陈述是否有申请或要求范围?阅读完文档后,在应用程序级对其进行缩放以减少准备阶段的数量似乎更有效。但是,也许还有其他考虑因素,并且准备好的陈述并非旨在长期存在?Go sql - 准备语句范围

回答

1

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

它们并不意味着长时间地处于“长期”状态,因为预先准备的语句可能(它们在事务中调用时)会保留活动的数据库连接(“long”意味着它们不被使用时;意味着重复执行准备好的声明多次,即使这需要很长时间)。连接是一种昂贵的资源,只能根据需要进行保存。只需创建一堆准备好的语句而不关闭它们,就可以用完主动/允许的连接,然后阻止与数据库服务器的进一步通信。

如果您想在一个HTTP请求中多次执行与多个不同参数相同的insertupdateselect语句,请使用准备好的语句。不要使用准备好的语句来使(HTTP)请求活跃起来。

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

在Go中有一篇文章(由Myles McDonnell在下面的评论中发布)进入Prepared Statements的实现细节。它提到,如果预处理语句不是从事务创建的,它们会将连接释放回连接池,但在需要时,它们会尝试重复使用它们准备的连接(因为如果db服务器辅助/也扮演主动角色在准备好的语句中,它绑定到服务器端的连接)。如果没有,他们将重新准备他们在一个新的连接(造成不良的性能开销)。总而言之,您所描述的是一种工作模式,如果您在许多后续请求中需要/执行的准备好的语句数量较少,则可能意味着响应时间缩短。但是,这也意味着另一方面,从长远来看,它们可能会导致所有准备好的陈述都将在所有关联池中进行准备。决定你的情况是否可以接受。

通常应该避免这种情况(并且在HTTP请求结束之前关闭预准备语句),但是如果您只有少数几个请求,并且您在多个请求之后确实需要它们,则可以将它们移动超出请求范围。

+1

我的理解是,prep.stmt会将它准备回来的conn释放回池中。然后,stmt会在执行时尝试使用该conn,但如果conn不可用,则会再次准备新的conn(本身就是潜在的可伸缩性问题)。考虑到为语句创建和分配资源的费用,由于我的应用程序的语句数量有限,因此在应用程序范围内提前创建它们似乎合乎逻辑。我并不是不同意你的观点,我可能是错误的,但我对此没有足够的理解。 –

+0

连接和预准备语句之间的WRT关系; http://go-database-sql.org/prepared.html –