2016-01-13 56 views
0

在我当前的项目中,我们在系统中有多个搜索页面,我们从数据库中获取大量数据以显示在UI中的大表格元素中。我们使用JPA进行数据访问(我们的提供者是Hibernate)。大多数页面的数据都是从多个数据库表中收集的 - 在许多情况下大约为10个 - 包括来自OneToMany关系的一些汇总数据(例如“类型X的关联实体的数量”)。为了提高性能,我们使用TypedQuery.setFirstResult()TypedQuery.setMaxResults()的结果集分页,以便在用户滚动表格时从数据库中延迟加载额外的行。由于搜索非常动态,因此我们使用JPA CriteriaQuery API构建查询。但是,我们目前有些受到N + 1 SELECT问题的困扰。在某些情况下,它确实很糟糕,因为我们可能会迭代3层嵌套的OneToMany关系,其中每个级别的数据都是延迟加载的。我们不能真正将这些集合声明为在实体映射中加载的,因为我们只在某些页面中对它们感兴趣。即我们可能会在几个不同的页面中从同一个表中获取数据,但是我们会在表中显示不同的数据,并显示不同页面中的不同关联表。JPA实体图表和分页

为了减轻这一点,我们开始尝试使用JPA实体图,并且它们似乎对N + 1 SELECT问题有很大帮助。但是,当您使用实体图时,Hibernate显然会在内存中应用分页。我可以稍微理解为什么它会这样做,但是这种行为在许多情况下否定了很多(如果不是全部的话)实体图的好处。当我们不使用实体图时,无论应用任何WHERE限制(即将整个表视为结果集),我们都可以加载数据,无论表中有多少百万行,因为只有非常有限的行实际上由于分页而被提取。既然分页是在内存中完成的,Hibernate基本上会获取整个数据库表(加上在实体图中定义的所有关系),然后在内存中应用分页,将剩余的行丢弃。不好。

所以问题是,有没有一种有效的方法来应用分页和实体图与JPA(休眠)?如果JPA没有提供解决方案,那么Hibernate特定的扩展也是可以接受的。如果这也不可能,那么其​​他的选择是什么?使用数据库视图?由于我们支持多个数据库供应商,所以视图会有点麻烦。为不同的供应商创建所有必要的视图会大大增加开发工作量。

我的另一个想法是应用实体图和分页,就像我们目前所做的那样,如果它们返回的行太多,根本不会触发任何查询。我已经需要做COUNT查询才能让行的延迟加载在UI中正常工作。

回答

2

我不确定我是否完全理解您的问题,但我们遇到了类似的情况:我们已分页列出可能包含来自多个联合实体的数据的实体。这些列表可能会被排序和过滤(由于缺少dbms中的功能,这些排序/过滤器必须应用于内存中,但这只是一个附注),然后应该应用分页。

保持在内存中的所有数据,所以我们采取了以下方法不能很好地工作(有可能是更好/更标准的):

  1. 使用查询来加载主键(在简单的多头我们的案例)的主要实体。只加入排序和筛选所需的内容,以尽可能简化查询。

    在我们的情况下,查询将实际加载更多的数据在内存中应用排序和过滤器在必要时,但该数据被释放尽快,只有主键被保留。
  2. 显示特定页面我们提取一个页相应的主键和使用第二查询加载的一切,是该网页上显示时。这第二个查询可能包含多个连接,从而更加复杂,比在第1步速度较慢,但​​由于我们只对页面加载数据的系统上的实际负担是相当低的。
+0

你的情况听起来很相似,我们(我们也有一大堆的动态过滤器和需要分页之前要应用排序规则)。我实际上考虑过尝试类似的解决方案,但认为这样做效率太低。但显然它不是?因此,在第2步中,您使用主要实体的主键在查询中定义了一个IN条件?我有点担心,我可能会遇到[HHH-9230(https://hibernate.atlassian.net/browse/HHH-9230)如果我这样做(我们仍然在使用Hibernate 4.x版)。再说,你永远不知道,直到你试试:) –

+0

我尝试了你提出的办法,似乎工作得很好。至少我最初的印象是它比Hibernate的内存分页快很多,但我还没有做过任何具体的测量。我没碰上[HHH-9374(https://hibernate.atlassian.net/browse/HHH-9374)运行时,某些查询,虽然,但我希望升级Hibernate会解决。谢谢你的回答! –

+0

@MarkusYrjölä我很高兴听到它的作品。我们也使用4.x,所以它应该可以工作(尽管我们没有使用实体图)。我想补充的一件事是:由于第二个查询的where条件可能会导致相当大的声明,我们通常将其拆分并发出多个查询。根据我们的经验,在“更小”查询/结果导致性能提升超过您通过使用多个查询而不是一个查询而获得的处罚的情况下,会有一个甜蜜点/区域。甜蜜点可能会有所不同,但250-500的大小对我们来说工作得相当好。 – Thomas