与在pgadmin中执行查询相比,使用JDBC执行Postgresql查询需要更多时间

时间:2016-09-28 11:10:33

标签: java postgresql jdbc

我有一个存储过程,带有参数(参数)

我们称之为x

当我跑步时,

select * from x('myParameter')

它在4分钟内完成。

现在我尝试在java中执行相同的存储过程,如下所示: -

PreparedStatement statement = connection.prepareStatement("Select * from x('myParameter')");
org.postgresql.PGStatement pgstmt = (org.postgresql.PGStatement)statement;
pgstmt.setPrepareThreshold(1);
boolean usingServerPrepare = pgstmt.isUseServerPrepare();
System.out.println(usingServerPrepare);
statement.execute();

这需要大约26个小时才能完成。

我最初在没有pgstmt.setPrepareThreshold(1);的情况下尝试, 即prepareThreshold的默认值。 结果是一样的。

然后我尝试使用"设置enable_nestloop false"作为存储过程的第一行,它在4分钟内完成。

当我明确强制使用服务器端预处理语句时,我无法理解为什么查询会更改执行计划。

我正在使用Postgres 9.4和Java 8.我也在使用PGBouncer进行连接池。

我的问题是 - 为什么JDBC会影响执行计划呢?有没有办法强制服务器端执行计划到我从java程序触发的查询?

1 个答案:

答案 0 :(得分:2)

得到解决方案: - 存储过程中使用的表格为" tab1"。

当我们从PGAdmin / SQL窗口运行存储过程时,tab1已经在几小时后创建/修改。

在自动运行中,使用java,在执行存储过程前几秒创建并加载/修改tab1。
在第一种情况下(从PGAdmin / SQL窗口运行存储过程)tab1上的自动分析在PGAdmin中运行存储过程时已完成,而在第二种情况下(自动运行)使用java )tab1上的自动分析尚未启动或正在处理,因为tab1刚被修改。 这使得Postgres在从PGAdmin运行查询时选择更好的计划,与我们使用java运行时相比。

摘要 - 选择了不同的计划,因为在第二种情况下,自动分析在我们运行存储过程时没有完成,导致查询计划选择不佳。