hibernate与很多实体的性能

时间:2013-03-05 16:01:33

标签: java performance hibernate nhibernate

我有以下代码行:

  

log4net.LogManager.GetLogger(“m”)。Debug(DateTime.Now.ToString(“hh:mm:ss.fff”)+“Check-1”);

     

设置setting = session.CreateQuery(“来自设置s”)。UniqueResult<设置和GT;();

     

log4net.LogManager.GetLogger(“m”)。Debug(DateTime.Now.ToString(“hh:mm:ss.fff”)+“Check-2”);

上面的代码执行时间小于毫秒(Check-1和Check-2中的时间相同,它以毫秒为单位测量时间,并且代码中未显示使用的条件。)

但在这种情况下:

  

的IList<票> tickets = session.CreateQuery(“来自Ticket”)。列表<票>();

     foreach(门票票)
  {
  t.Dosomething = 5;
  log4net.LogManager.GetLogger(“m”)。Debug(DateTime.Now.ToString(“hh:mm:ss.fff”)+“Check-1”);   设置setting = session.CreateQuery(“来自设置s”)。UniqueResult<设置>();   log4net.LogManager.GetLogger(“m”)。Debug(DateTime.Now.ToString(“hh:mm:ss.fff”)+“Check-2”);
  }

上面的代码是处理大量数据的巨大处理代码的简化版本,我需要在foreach循环中进行另一个查询。 forech循环中的查询在500ms内执行。故障单集合包含15000行。

我已经重新考虑了代码(在foreach中没有查询),但我感兴趣的是,如果单独执行相同的查询没有时间执行,但如果在首先加载大量实体​​后执行,它会变得如此之慢?

但是在上面的相同场景中,如果我在第二个查询中使用不同的会话,它会立即执行。

当我需要在大量实体的foreach循环中执行另一个查询时,如何处理这些情况的任何建议?

3 个答案:

答案 0 :(得分:2)

NHibernate默认跟踪会话中加载的对象(第一级缓存)。在进行查询时,NHibernate会检查某些加载的对象是否有可能影响查询结果的更改 - 必须将这些更改刷新到数据库,以便查询可以返回正确的结果。加载的对象越多,此过程所需的时间就越长。

NHibernate和ISession针对拥有相对较少数量的已加载对象进行了优化,这不是问题。

这些是提高批处理方案性能的一些技巧:

  • 尝试将作品分成可以在单独的交易和会话中独立运行的较小部分。

  • 如果您将工作划分为较小的部分,则可以在战略要点(每个独立部分之后)使用session.Flush()session.Clear()来清除更改并保留跟踪对象的数量合理的水平。使用此策略,所有部件都可以在同一事务中运行。

  • 查看session.FlushMode以禁用自动刷新查询。使用FlushMode.CommitNever结合显式调用Flush()。但查询结果可能无法反映早先在同一工作单元中执行的更改。

答案 1 :(得分:1)

尝试使用投影将票证加载到DTO中,然后再迭代它们。 Hibernate跟踪会话中的所有已加载对象,直到它被刷新为止,使用投影加载您需要的数据将意味着Hibernate不需要加载和跟踪对象。

答案 2 :(得分:0)

最好连接两个表并获取结果,而不是获取第一个表记录,迭代然后获取第二个表记录。

满足您的更多要求