PreparedStatement非常慢,但手动查询速度很快

时间:2015-01-30 13:18:21

标签: java postgresql jdbc ofbiz

我有一个来自以下框架的预备陈述:

SELECT OH.ORDER_ID, MAX(OS.STATUS_DATETIME) FROM public.ORDER_HEADER OH, public.ORDER_STATUS OS WHERE ((OH.ORDER_ID = OS.ORDER_ID AND OH.STATUS_ID = ? AND OS.STATUS_ID = ?)) GROUP BY OH.ORDER_
ID HAVING (MAX(OS.STATUS_DATETIME) <= ?) ORDER BY OH.ORDER_ID ASC

OrderHeader有30万行,OrderStatus大约有5-6万行。 所有查询的字段都有一个索引。数据库是Postgres 9.1

SELECT OH.ORDER_ID, MAX(OS.STATUS_DATETIME) FROM ORDER_HEADER OH INNER JOIN ORDER_STATUS OS 
    ON ((OH.ORDER_ID = OS.ORDER_ID AND OH.STATUS_ID = 'ORDER_PARTIALLY_RECEIVED' AND OS.STATUS_ID = 'ORDER_PARTIALLY_RECEIVED'))
     GROUP BY OH.ORDER_ID HAVING (MAX(OS.STATUS_DATETIME) <= '2015-01-27 00:00:00') ORDER BY OH.ORDER_ID ASC

这是参数替换时的查询字符串。

从Java运行查询,作为PreparedStatement和在其中设置的参数使查询运行几分钟(5-6分钟)。 当我手动运行SQL时,需要10秒钟。 这怎么可能,我该如何解释呢?

3 个答案:

答案 0 :(得分:4)

在不知道实际参数的情况下优化预备语句。在PostgreSQL 9.1中,预处理语句仅针对大多数常见值进行了优化。当准备好的语句很慢时,您必须使用动态SQL。 PostgreSQL具有很好的API - 参数化查询 - 它是在预准备语句和常规查询之间进行的 - 它可以安全地防止SQL注入,并且它可以免受盲目优化的问题。

答案 1 :(得分:1)

如果结果集很大 - PreparedStatement可能工作得更慢,因为默认&#34; fetchSize&#34;只有10岁。 尝试为此查询设置更大的fetchSize。 更多信息:http://docs.oracle.com/cd/A97335_02/apps.102/a83724/resltse5.htm
特别是Postgres:https://jdbc.postgresql.org/documentation/head/query.html

答案 2 :(得分:0)

如果使用prepareStatements,则必须标识参数类型。您可以解释sql。 例如 uid类型为整数 explain analyse select * from users where uid in (200,500,800); PREPARE fooplan (int, int, int) AS select * from users where uid in ($1, $2, $3); explain analyse EXECUTE fooplan(200, 500, 800); PREPARE fooplan1 (numeric, numeric, numeric) AS select * from users where uid in ($1, $2, $3); explain analyse EXECUTE fooplan1(200, 500, 800); PEP 498