我在 JBoss EAP 7.4.9 上使用 JPA Criteria API,因为我必须根据 GUI 上应用的过滤器动态生成不同的 SQL。 到目前为止,这种方法已经奏效,但在向 Oracle DB 添加数百万个条目后,性能大幅下降,以至于应用程序无法使用。
我查看了生成的SQL(完整的SQL中有一些Join):
select * from ( select ... where (component = '...' ) and (delivered = 'Delivered' ) and rownum <= 200 order by entrytime desc );
这将在大约 30 秒内执行。
我通过删除外部选择来修改 SQLDeveloper 中的 sql:
select ... where (component = '....' ) and (delivered = 'Delivered' ) and rownum <= 200 order by reportmess0_.entrytime desc ;
令我惊讶的是,它在较低的毫秒范围内执行。
有什么方法可以阻止 JPA / Criteria API 生成此外部选择吗? 任何提示将不胜感激。
您不想删除外部查询,因为它正在生成内联视图并且不应该影响性能。
但是,您的疑问:
select *
from (
select ...
where (component = '...' )
and (delivered = 'Delivered' )
and rownum <= 200
order by entrytime desc
);
(可能)不正确,因为
WHERE ... rownum <= 200
过滤器将在 ORDER BY
子句之前应用,因此您将获得与所有 WHERE
过滤器匹配的前 200 行(随机选择)行,然后对这 200 行进行排序.
如果您要对结果进行分页,那么您(可能)想要的是首先对结果集进行排序,然后获取前 200 行,这样您就可以获得具有最新日期的行,而不是对随机选择的行进行排序。
select *
from (
select ...
where (component = '...' )
and (delivered = 'Delivered' )
order by entrytime desc
);
where rownum <= 200
但这会比第一个查询的性能较差,因为它必须对整个结果集进行排序,然后获取最新的 200 行。
然后你可以看看加速查询的技术,例如:添加索引;或对表进行分区。