【问题标题】:Java, JDBC: Does closing a PreparedStatement also free up its memory footprint in the database connection?Java、JDBC:关闭 PreparedStatement 是否也会释放其在数据库连接中的内存占用?
【发布时间】:2019-10-22 10:58:57
【问题描述】:

据我了解,每次初始化 PreparedStatement 时,该语句都会缓存在为数据库连接分配的内存中。因此,如果初始化过多的PreparedStatement 变量,则存在溢出可用于连接的内存的风险。

  1. 是否通过在 PreparedStatement 实例上调用 close() 来释放缓存的内存?

  2. 两个包含相同 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();
}

【问题讨论】:

  • "立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待它自动关闭时发生这种情况。通常在完成资源后立即释放资源以避免捆绑数据库资源。”
  • 你的问题太宽泛了。您正在为两个不同的数据库(MySQL 和 PostgreSQL)询问两个不同的事情(关闭时释放内存,并在 PreparedStatement 实例之间共享准备好的语句信息)。每个问题请专注于一件事。

标签: java mysql sql postgresql jdbc


【解决方案1】:

1> 并非所有驱动程序都支持预编译。 2> JDBC 和 Database 都会在必要时执行缓存驱逐。

Oracle JDBC 驱动示例:

来源:https://docs.oracle.com/cd/B28359_01/java.111/b31224/stmtcach.htm

从缓存中删除语句以符合最大大小 使用最近最少使用 (LRU) 算法。

【讨论】:

    【解决方案2】:

    两者都回答:这完全取决于 JDBC 驱动程序。

    例如PostgreSQL JDBC 驱动见Server Prepared Statements:

    当使用PreparedStatement API 时,驱动程序使用服务器端准备好的语句默认。为了进行服务器端准备,您需要执行 5 次查询(可以通过prepareThreshold 连接属性进行配置)。内部计数器会跟踪语句执行了多少次,当它达到阈值时,它将开始使用服务器端准备好的语句。

    出于性能原因,重用相同的PreparedStatement 对象通常是个好主意,但是驱动程序能够跨connection.prepareStatement(...) 调用自动为服务器准备语句。

    [...]

    服务器准备的语句在客户端和服务器上都消耗内存,因此 pgjdbc 限制每个连接的服务器准备语句的数量。它可以通过preparedStatementCacheQueries(默认256,pgjdbc 已知的查询数量)和preparedStatementCacheSizeMiB(默认5,即每个连接的客户端缓存大小,以兆字节为单位)进行配置。只有statement cache 的一个子集是服务器准备的,因为某些语句可能无法到达prepareThreshold

    有关 MS SQL Server JDBC 驱动程序,请参阅Prepared Statement Metadata Caching for the JDBC Driver

    对于 MySQL JDBC 驱动程序,请参阅Prepared Statement Cache with MySQL & JDBC 的答复。

    我没有看到 Oracle JDBC 驱动程序的任何此类功能。

    【讨论】:

      猜你喜欢
      • 2012-08-28
      • 2020-01-12
      • 2011-05-11
      • 1970-01-01
      • 2021-04-27
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      相关资源
      最近更新 更多