我有一个来自以下框架的预备陈述:
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秒钟。 这怎么可能,我该如何解释呢?
答案 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