据我了解,每次初始化
PreparedStatement
时,该语句都会缓存在为数据库连接分配的内存中。因此,如果初始化过多的 PreparedStatement
变量,则存在连接可用内存溢出的风险。
是否通过在
close()
实例上调用 PreparedStatement
释放缓存内存?执行两个包含相同 SQL 的
PreparedStatement
创建重复的缓存事件,或者数据库是否足够智能,不会缓存重复 PreparedStatement
的新实例?示例1,这样会导致连接内存溢出吗?:
while (true) {
PreparedStatement ps = connection.prepareStatement("SELECT id + ? FROM tbl");
ps.setDouble(1, Math.random());
ps.executeQuery();
ps.close();
}
如果可以的话,那这个呢?:
while (true) {
PreparedStatement ps = connection.prepareStatement("SELECT id FROM tbl");
ps.executeQuery();
ps.close();
}
两者的答案:这完全取决于 JDBC 驱动程序。
例如对于 PostgreSQL JDBC 驱动程序,请参阅服务器准备语句:
JDBC 驱动程序的准备语句元数据缓存Prepared Statement Cache with MySQL & JDBC当使用
PreparedStatement
API 时,驱动程序默认使用服务器端准备好的语句。为了进入服务器端准备,您需要执行查询 5 次(可以通过连接属性进行配置)。内部计数器跟踪语句已执行的次数,当达到阈值时,它将开始使用服务器端准备好的语句。出于性能原因,重用相同的prepareThreshold
PreparedStatement
对象通常是一个好主意,但是驱动程序能够跨
调用自动服务器准备语句。[...]connection.prepareStatement(...)
服务器准备的语句会消耗客户端和服务器上的内存,因此 pgjdbc 限制每个连接的服务器准备的语句数量。它可以通过
preparedStatementCacheQueries
(默认
,pgjdbc 已知的查询数量)和256
(默认preparedStatementCacheSizeMiB
,即每个连接的客户端缓存大小(以 MB 为单位)进行配置)。只有5
的子集是服务器准备的,因为某些语句可能无法到达statement cache
。 对于 MS SQL Server JDBC 驱动程序,请参阅prepareThreshold
的答案。 我没有看到 Oracle JDBC 驱动程序有任何此类功能。