【发布时间】:2022-01-13 10:35:36
【问题描述】:
在使用分页访问 Oracle 12.1 表时,我们遇到了 EclipseLink 2.7.7 的性能问题。调查表明,Oracle 不会将其索引与 EclipseLink 分页一起使用。
我已提取发送到数据库的 sql,并且能够使用数据库工具 (DataGrip) 重现该问题。
例子:
-- #1: without paging
SELECT col1 AS a1, col2 AS a2, col3 AS a3, ...
FROM <TABLE>
WHERE colN > to_timestamp('2021-12-08', 'yyyy-mm-dd'))
ORDER BY col1 DESC;
解释计划显示使用了colN 上的索引。很好。
当使用分页执行相同的查询时,原始查询被包装在两个子选择中:
-- #2 with EclipseLink paging
SELECT * FROM (
SELECT a.*, ROWNUM rnum FROM (
SELECT col1 AS a1, col2 AS a2, col3 AS a3, ...
FROM <TABLE>
WHERE colN > to_timestamp('2021-12-08', 'yyyy-mm-dd'))
ORDER BY col1 DESC
) a WHERE ROWNUM <= 100
) WHERE rnum > 0;
对于此查询,解释计划显示colN 上的索引未使用。
因此,查询具有数百万行的表需要 50-90 秒(取决于硬件)。
旁注:在我的测试数据库中,此查询返回 0 条记录,因为 colN 值在 2021-12-08 之前。
Oracle 12c 引入了 OFFSET/FETCH 语法:
-- #3
SELECT col1 AS a1, col2 AS a2, col3 AS a3, ...
FROM <TABLE>
WHERE colN > to_timestamp('2021-12-08', 'yyyy-mm-dd'))
ORDER BY col1 DESC
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;
使用这种语法,索引至少有时会按预期使用。使用它们时,执行时间低于 1s,这是可以接受的。 但是,我不知道如何说服 EclipseLink 使用这种语法。
如果 ORDER BY col1 DESC 从原始分页查询 (#2) 中删除,则使用索引,查询返回速度足够快。但是,它不会返回所需的记录,因此无济于事。
如何使用 EclipseLink 和 Oracle 12 实现高性能的分页查询?
使用分页和order by时如何强制oracle使用colN上的索引?
【问题讨论】:
标签: oracle eclipselink