PostgreSQL报错:number of bytes should be at-least 8
用PrepareStatement多次查询时报错:
Caused by: java.lang.IllegalArgumentException: number of bytes should be at-least 8
at org.postgresql.util.ByteConverter.numeric(ByteConverter.java:127)
at org.postgresql.util.ByteConverter.numeric(ByteConverter.java:111)
at org.postgresql.jdbc.PgResultSet.getNumeric(PgResultSet.java:2651)
at org.postgresql.jdbc.PgResultSet.internalGetObject(PgResultSet.java:228)
at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:2904)
at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:2917)
分析原因:JDBC里的执行计划选择不正确,当表的数据分布不均匀,且SQL传递参数不一样时,PrepareStatement仍然用的原来的执行计划。prepareThreshold参数默认是5,客户端会编译并缓存preparestatement的执行计划,设置为0就能禁用客户端缓存。
- prepareThreshold :server prepare开关
- 当为0时,禁用server prepare。相当于每次SQL都是硬解析。
- 当为1时,开启server prepare。相当于每次都走服务端的缓存。复用已有的SQL解析结果和执行计划,不进行SQL解析。
- 当n大于1时,执行第n次时开启server prepare。相当于从第N次开始复用SQL解析结果和执行计划,不进行SQL解析。
解决方法:在jdbc url上设置参数"prepareThreshold=0"