java - Java、JDBC:关闭 PreparedStatement 是否也会释放其在数据库连接中的内存占用?
问题描述
据我了解,每次PreparedStatement
初始化 a 时,该语句都会缓存在为数据库连接分配的内存中。因此,如果初始化过多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 驱动程序,请参阅Server Prepared Statements:
使用API时,驱动程序默认使用服务器端准备好的语句。
PreparedStatement
为了进行服务器端准备,您需要执行 5 次查询(可以通过prepareThreshold
连接属性进行配置)。内部计数器跟踪语句执行了多少次,当它达到阈值时,它将开始使用服务器端准备好的语句。出于性能原因,重用同一个对象通常是一个好主意,但是驱动程序能够跨调用
PreparedStatement
自动准备服务器语句。connection.prepareStatement(...)
[...]
服务器准备的语句在客户端和服务器上都消耗内存,因此 pgjdbc 限制每个连接的服务器准备语句的数量。它可以通过
preparedStatementCacheQueries
(默认256
,pgjdbc 已知的查询数)和preparedStatementCacheSizeMiB
(默认5
,即客户端缓存大小,以每个连接的兆字节为单位)进行配置。只有一个子集statement cache
是服务器准备的,因为某些语句可能无法到达prepareThreshold
.
对于 MS SQL Server JDBC 驱动程序,请参阅为 JDBC 驱动程序准备的语句元数据缓存。
对于 MySQL JDBC 驱动程序,请参阅Prepared Statement Cache with MySQL & JDBC 的回答。
我没有看到 Oracle JDBC 驱动程序的任何此类功能。
推荐阅读
- java - 如何使用 Spring Framework 按数组中的最新和最早日期对 Elasticseach 中的值进行排序?
- hyperledger-fabric - 为什么我在安装超级账本结构时收到“tar: Error opening archive: Unrecognized archive format”错误
- javascript - 无法部署firebase云功能
- c# - 如何在 EF Core 5 中创建 3 种方式的关系
- sql - 多个未嵌套匹配自定义维度 BigQuery
- kubernetes - kubernetes - 选择部署而不是 daemon-set 的用例
- stripe-payments - 在支付网关中根据支付方式处理交易费用
- typescript - 键入'{ placeholderText:字符串;键盘类型:字符串;}' 不可分配给类型 'IntrinsicAttributes & IntrinsicClassAttributes
- javascript - 当我在反应本机 redux 中更新状态时,会删除以前的状态
- rest - REST API 请求帮助(POST 方法)