Java 仅当查询包含第一行或行数限制时,ResultSet.next速度非常慢

Java 仅当查询包含第一行或行数限制时,ResultSet.next速度非常慢,java,oracle,jdbc,eclipselink,Java,Oracle,Jdbc,Eclipselink,我使用 entityManager.createNativeQuery(sqlQuery); query.setMaxResults(maxResults); List<Object[]> resultList = query.getResultList(); entityManager.createNativeQuery(sqlQuery); query.setMaxResults(maxResults); List resultList=query.getResultList

我使用

entityManager.createNativeQuery(sqlQuery);
query.setMaxResults(maxResults);

List<Object[]> resultList = query.getResultList();
entityManager.createNativeQuery(sqlQuery);
query.setMaxResults(maxResults);
List resultList=query.getResultList();
为了加快查询速度,我想使用
WHERE ROWNUM>n
包含
FIRST\u ROWS(n)
提示或限制


通过使用指令插入,我发现实际上
OraclePreparedStatement.executeQuery
速度更快,但在
EJBQueryImpl.getResultList
上花费的时间更多,导致整体性能非常差。更详细地看,我发现每隔10次调用
ResultSet.next()
所花的时间大约与executeQuery本身()的时间一样长。当我忽略查询提示或ROWNUM条件时,这种奇怪的行为就会停止,然后每隔10次调用resultset.next会比其他调用稍微低一些,但只有2毫秒而不是3秒。

当包含提示时,您会得到不同的查询计划吗?我的假设是,你这样做是基于你对问题的描述

当您在Oracle中执行查询时,数据库通常不会在任何时间点具体化整个结果集(显然,如果您指定了一个
orderby
子句,该子句要求在进行排序之前具体化所有数据,则可能必须这样做)。在客户端开始提取数据之前,Oracle实际上不会开始具体化数据。它运行足够多的查询,以生成客户机请求获取的行数(在您的情况下听起来像是10行),将这些结果返回给客户机,并等待客户机请求更多数据,然后继续处理查询


听起来,当包含
FIRST_ROWS
提示时,查询计划正在以一种更昂贵的方式进行更改。显然,这不是
FIRST\u ROWS
提示的目标。目标是告诉优化器生成一个计划,使前N行的获取效率更高,即使这会降低从查询中获取所有行的效率。这往往会导致优化器更喜欢索引扫描而不是表扫描,因为表扫描总体上可能更有效。然而,在您的案例中,优化器的估计是不正确的,它最终选择了一个通常效率较低的计划。这通常意味着查询引用的某些对象的某些统计信息不完整或不正确

尝试直接将最大行数限制添加到SQL中,而不是使用setMaxResults,即将where rownum听起来您让JDBC executeQuery更快了,但JDBC ResultSet下一步会更慢。您提高了执行查询的速度,但降低了获取数据的速度。这似乎是JDBC的问题,而不是EclipseLink,如果您实际获取了数据,您将通过原始JDBC获得相同的结果

10是默认的获取大小,因此您可以尝试将其设置为更大

看,,

谢谢。我对n之后的行不感兴趣,这也是我使用setmaxresults的原因。当使用
ROWNUM
而不是查询提示时,也存在问题,因此应该对其进行优化,以返回具有此限制的查询可以返回的所有n行。是的,我得到了不同的执行计划,但在SQL developer中,返回n行非常快,而与eclipselink一起使用时,持续时间似乎会乘以n/10。@stracktracer-您能发布查询和得到的各种查询计划吗?SQL开发人员计划与eclipselink计划相同吗?默认情况下,SQLDeveloper只返回前50行数据。您确定您要求SQL Developer获取所有数据并测量该时间,而不仅仅是测量获取前50行所需的时间吗?增加了获取大小。现在有更少的慢
next
s,但不幸的是,其余的慢
s按比例变长,因此总持续时间不受影响。如果我将fetch size设置为ROWNUM number,那么只有executeQuery需要非常长的时间。