java - 具有大量实体的 hibernate 性能

标签 java performance hibernate nhibernate

我有以下代码行:

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

Setting setting = session.CreateQuery("from Setting s").UniqueResult< Setting>();

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

上面的代码执行时间不到毫秒(Check-1 和 Check-2 中的时间相同,并且以毫秒为单位测量时间,并且代码中未显示所使用的标准)。

但在这种情况下:

IList< Ticket> tickets = session.CreateQuery("from Ticket").List< Ticket>();

foreach(Ticket t in tickets)
{
t.Dosomething = 5;
log4net.LogManager.GetLogger("m").Debug(DateTime.Now.ToString("hh:mm:ss.fff") + " Check-1"); Setting setting = session.CreateQuery("from Setting s").UniqueResult< Setting>(); log4net.LogManager.GetLogger("m").Debug(DateTime.Now.ToString("hh:mm:ss.fff") + " Check-2");
}

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

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

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

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

最佳答案

NHibernate 默认情况下跟踪 session 中加载的对象(一级缓存)。当进行查询时,NHibernate 检查某些加载的对象是否发生了可能影响查询结果的更改 - 此类更改必须刷新到数据库,以便查询可以返回正确的结果。加载的对象越多,此过程花费的时间就越长。

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

以下是提高批处理场景性能的一些技巧:

  • 尝试将工作划分为更小的部分,这些部分可以在单独的事务和 session 中独立运行。

  • 如果您已将工作分成更小的部分,则可以在战略点(在每个部分之后)使用 session.Flush()session.Clear()独立部分)以刷新更改并将跟踪对象的数量保持在合理的水平。通过这种策略,所有部分都可以在同一个事务中运行。

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

关于java - 具有大量实体的 hibernate 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15228436/

相关文章:

Java在printf中打印双值零

集群环境中的数据库 ID 生成

java - Java 中的通用枚举

java - 由于以下问题无法启动服务器 : java. lang.NullPointerException

database - 使 SQL Server 数据库脱机时等待时间过长

performance - Haskell 在生成斐波那契数时(看似)随机暂停

database - Oracle直方图和读取错误索引

java - jpa实体映射情侣表

hibernate - 如何从 Grails Controller 和 View 外部引用 Grails 域类字段?

java - 在 ReSTLet 中的 HTTP 方法内创建客户端请求