我有一个存储过程,带有参数(参数)
我们称之为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程序触发的查询?
答案 0 :(得分:2)
得到解决方案: -
存储过程中使用的表格为" tab1"。
当我们从PGAdmin / SQL窗口运行存储过程时,tab1已经在几小时后创建/修改。
在自动运行中,使用java,在执行存储过程前几秒创建并加载/修改tab1。
在第一种情况下(从PGAdmin / SQL窗口运行存储过程)tab1上的自动分析在PGAdmin中运行存储过程时已完成,而在第二种情况下(自动运行)使用java )tab1上的自动分析尚未启动或正在处理,因为tab1刚被修改。
这使得Postgres在从PGAdmin运行查询时选择更好的计划,与我们使用java运行时相比。
摘要 - 选择了不同的计划,因为在第二种情况下,自动分析在我们运行存储过程时没有完成,导致查询计划选择不佳。