【问题标题】:Java PostgreSQL error on large query: An I/O error occurred while sending to the backend大型查询中的 Java PostgreSQL 错误:发送到后端时发生 I/O 错误
【发布时间】:2016-12-18 00:57:28
【问题描述】:

在 Java 中,我尝试使用 java.sql.PreparedStatement 提交一个相当大的查询,其中包含用于高效连接的常量 (VALUES (?), (?), (?)...) 表达式。

有 cca​​ 250K 的值,所以我也设置了 250K 参数。

在 Java 中,我得到了

org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.

在我的服务器 PostgreSQL 日志中,有一行关于该错误:

incomplete message from client

知道我可以在任何地方更改一些设置以使我的大型查询正常工作吗?

【问题讨论】:

  • 您正在尝试使用 250000 个参数执行 PreparedStatement?有你的问题。尝试创建一个临时。表,而是使用批量插入该表,然后加入临时表。表。
  • @Andreas 我明白你的意思,谢谢,我可能不得不做类似的事情。我知道 250K 很多,但是,只要计算机没有情绪,它一定是我已经达到的某个限制。我的问题是关于这个限制以及我是否可以增加它。我读过 psql 查询大小限制为 1GB,但我的参数是短标识符,它必须在其他地方......
  • 限制可能取决于 JDBC 驱动程序; some drivers 将限制设置为 2k。我同意安德烈亚斯;使用带有addBatch() 的普通插入或驱动程序支持的其他一些批量插入变体。
  • @MickMnemonic 它不是驱动程序,但主要是服务器的限制。驱动程序可能只是预先执行限制,有时稍微低一些。例如。 MS SQL 2016 最大。每个存储过程有 2100 个参数(请参阅msdn.microsoft.com/en-us/library/ms143432.aspx),我相信 JDBC 驱动程序为 PreparedStatements 使用临时存储过程。

标签: java postgresql jdbc limits


【解决方案1】:

JDBC 驱动程序可以传递给后端的最大参数数量为 32767。这受到 v3 有线协议的限制,该协议以 16 位 int 形式传递参数计数(请参阅definition of the Bind message 的文档)。

您可以通过在数组中传递值并在服务器上取消嵌套来解决此问题:

// Normally this would be one too many parameters
Integer[] ids = new Integer[Short.MAX_VALUE  + 1];
Arrays.setAll(ids, i -> i);
// Pass them in an array as a single parameter and unnest it 
PreparedStatement stmt = con.prepareStatement(
    "WITH ids (id) AS (SELECT unnest (?)) " +
    "SELECT f.* FROM foo f JOIN ids i ON i.id = f.id"
);
stmt.setArray(1, con.createArrayOf("INT", ids));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2020-07-22
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多