Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring数据存储库-分页大型数据集(EclipseLink)_Spring_Jpa_Pagination_Eclipselink_Spring Data - Fatal编程技术网

Spring数据存储库-分页大型数据集(EclipseLink)

Spring数据存储库-分页大型数据集(EclipseLink),spring,jpa,pagination,eclipselink,spring-data,Spring,Jpa,Pagination,Eclipselink,Spring Data,我使用Spring数据和EclipseLink JPA对数据库结果集进行服务器端分页。我的一切都正常工作,我得到了预期的分页结果,但我注意到在大数据集(数百万行)上性能下降。返回包含20个结果的页面大约需要5分钟。也许这是意料之中的,但我关心的是查询输出 我的日志输出: SELECT COUNT(filename) FROM document SELECT filename, datecaptured, din, docdate, docid, doctype, drawer, foldernu

我使用Spring数据和EclipseLink JPA对数据库结果集进行服务器端分页。我的一切都正常工作,我得到了预期的分页结果,但我注意到在大数据集(数百万行)上性能下降。返回包含20个结果的页面大约需要5分钟。也许这是意料之中的,但我关心的是查询输出

我的日志输出:

SELECT COUNT(filename) FROM document
SELECT filename, datecaptured, din, docdate, docid, doctype, drawer, foldernumber, format, pagenumber, tempfilename, userid FROM document ORDER BY din ASC
我理解,为了进行分页,Spring需要知道最大行数,所以第一个查询是有意义的

第二个查询是拉取整个数据库,而我只要求20个偏移量为0的结果(第页)


Spring/EclipseLink/JPA是否实际上获取了整个数据集,然后只返回子集分页请求

如果是这样,我应该如何修改我的存储库类以提高效率

我的测试用例:

@Test
public void getPagedDocumentsTest() throws IOException {
    Page<Document> requestedPage = documentRepository.findAll(new PageRequest(0, 20, Sort.Direction.ASC, "din"));

    Assert.assertNotNull("Page is null", requestedPage);
    Assert.assertNotNull("Page is empty", requestedPage.getContent());

    List<Document> documents = requestedPage.getContent();

    LOG.info("{}", documents);
    LOG.info("{}", documents.size());
}
还尝试将其添加到我的配置中(我正在使用Java配置):

看起来平台设置正确

[EL Config]: connection: 2015-08-06 12:04:05.691--ServerSession(686533955)--Connection(1896042043)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
    platform=>SQLServerPlatform
    user name=> ""
    connector=>JNDIConnector datasource name=>null
))
但两者都没有帮助。SQL查询输出也保持不变

编辑

发现了一个与@Chris的答案类似的相关问题:


< P>你应该考虑的是你是否真的需要知道元素的页数/总数。如果您从一个包含数百万个元素的结果集中返回一个页面,那么您的用户很可能对浏览所有这些页面都不感兴趣:)。也许你的前端会在一个无限长的卷轴中显示数据,只需要知道是否还有更多的页面,而不是页面数

如果有任何情况适用于您,您应该考虑返回<代码>切片>代码>而不是<代码>页面<代码>,如:

public Slice<MyClass> findByMyField(..);
public Slice findByMyField(..);
这样,Spring数据就不会进行昂贵的
计数
,只会要求比您最初想要的多出一个元素。如果该元素存在,则
切片将从
hasNext
方法返回true


我在工作中,我们最近使用了几个大数据集的切片和正确的索引(以及之后):我们已经看到了一些非常显著的收益。

< P>你应该考虑的是你是否需要知道元素的页数/总数。如果您从一个包含数百万个元素的结果集中返回一个页面,那么您的用户很可能对浏览所有这些页面都不感兴趣:)。也许你的前端会在一个无限长的卷轴中显示数据,只需要知道是否还有更多的页面,而不是页面数

如果有任何情况适用于您,您应该考虑返回<代码>切片>代码>而不是<代码>页面<代码>,如:

public Slice<MyClass> findByMyField(..);
public Slice findByMyField(..);
这样,Spring数据就不会进行昂贵的
计数
,只会要求比您最初想要的多出一个元素。如果该元素存在,则
切片将从
hasNext
方法返回true


在我工作的地方,我们最近对几个大型数据集使用了切片,并使用了正确的索引(以及之后的:),我们看到了一些非常显著的收益。

EclipseLink 2.5源代码,我检查过它,我相信它支持以下数据库平台类中内置的数据库级过滤:

  • DB2Platform
  • 德比平台
  • 火鸟平台
  • H2平台
  • 汉娜平台
  • HSQL平台
  • MySQLPlatform
  • OraclePlatform
  • PostgreSQLPlatform
  • SymfowarePlatform
其中每一个都重写printSQLSelectStatement方法,以利用各自的数据库功能,允许在SQL本身中进行筛选。其他平台将需要使用JDBC过滤,这依赖于驱动程序来限制行-它们可能能够优化查询,但它是特定于驱动程序的,我相信这就是为什么查询比您希望的时间更长

我对SQLServer的了解还不够透彻,无法说出它具有哪些可以在SQL中使用的等效功能,但如果找到了,则需要创建一个SQLServerPlatform子类,像在上述类中那样重写printSQLSelectStatement方法,然后指定使用该平台类。还请提交一个bug/特性,以便将其包含在EclipseLink中

此处介绍了其他选项:

我查看的EclipseLink 2.5源代码我相信它支持以下数据库平台类中内置的数据库级过滤:

  • DB2Platform
  • 德比平台
  • 火鸟平台
  • H2平台
  • 汉娜平台
  • HSQL平台
  • MySQLPlatform
  • OraclePlatform
  • PostgreSQLPlatform
  • SymfowarePlatform
其中每一个都重写printSQLSelectStatement方法,以利用各自的数据库功能,允许在SQL本身中进行筛选。其他平台将需要使用JDBC过滤,这依赖于驱动程序来限制行-它们可能能够优化查询,但它是特定于驱动程序的,我相信这就是为什么查询比您希望的时间更长

我对SQLServer的了解还不够透彻,无法说出它具有哪些可以在SQL中使用的等效功能,但如果找到了,则需要创建一个SQLServerPlatform子类,像在上述类中那样重写printSQLSelectStatement方法,然后指定使用该平台类。还请提交一个bug/特性,以便将其包含在EclipseLink中

此处介绍了其他选项:

尝试指定EclipseLink将在持久性属性中使用的目标数据库平台,以确保如果设置了max和first结果,它将使用数据库筛选(SQL中内置的limit/rownum)而不是JDBC筛选。而不是
[EL Config]: connection: 2015-08-06 12:04:05.691--ServerSession(686533955)--Connection(1896042043)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
    platform=>SQLServerPlatform
    user name=> ""
    connector=>JNDIConnector datasource name=>null
))
public Slice<MyClass> findByMyField(..);