我怎么能阻止h2阻止我的hibernate查询呢

时间:2013-09-13 09:03:06

标签: hibernate h2

我已经通过hibernate使用h2(1.3.172)作为我的应用程序了一段时间,在解决了一些非h2性能问题后,我的性能瓶颈是h2。我的数据库很简单,有10个表,每个表的卷少于100,000个记录以及h2功能,但我认为问题在于多线程。

我实际上是在使用hibernate / h2来控制应用程序中的内存消耗。我的应用程序使用管道方法处理文件,对可处理的文件数量没有限制,因此如果我将数据存储在内存中,我会快速命中OutOfMemory。每个文件通常经历十个处理阶段,每个阶段都有自己的执行程序服务,当文件从一个阶段移动到另一个阶段时,它将作为作业添加到相关执行程序服务上。内存中存储的数据非常少,而在执行程序上启动作业时,将从数据库中检索有关文件的数据,并在作业完成时将数据写回数据库。我们有十个执行器,每个执行器都有一个机器核心大小的线程池,所以在一个4机器核心上我们理论上可以随时有40个数据库请求,但更典型的是我们有少于10个。所以我们有很多交易正在进行同时主要涉及少量行。

我的应用程序是多线程的,如果我对它运行一个分析器,我发现大多数时候我的线程处于阻塞状态,等待executeQuery()或executeUpdate()。我读到h2是单线程的,所以我认为问题是由h2同步请求引起的,而不是锁定但我可能误解了这一点。我已经设置了MVCC = TRUE,以便h2执行行而不是表锁定,但我仍然得到了ocassional超时 - 我可以设置一些东西来检查正在使用的锁。

我读到有一个MULTI_THREADING选项,但不能与MVCC一起使用,这是一种耻辱,因为我觉得我需要两个选项,如果我删除MVCC = TRUE这意味着h2会在每次插入时锁定表格或更新,因为我只有几个表,他们几乎总是被锁定。

所以,我觉得阻塞可能会大幅减少但我不清楚底层问题是什么以及如何继续

测试 这是我的起点,测试案例需要3分14秒

3:14,FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE

我尝试了各种组合,例如

3:02,FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;
2:56,FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;LOG=0;;CACHE_TYPE=SOFT_LRU;LOCK_MODE=0;
1:05,FILE_LOCK=SOCKET;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000

并且我发现唯一产生巨大差异的是移除MVCC = TRUE选项,但不幸的是我的锁定超时数从几乎为零增加到负载,所以不幸的是一些所需的处理没有发生,这可能是总时间更快的原因  因为应用程序中的某些阶段没有完成,或者使用MVCC会减慢速度。

我尝试使用MULTI_THREADED = TRUE,但它似乎根本不适用于我

关于在MultiCore系统中使用

我刚刚阅读了MULTI_THREADED选项https://groups.google.com/forum/#!topic/h2-database/VoE3AU7mSuM

的这个解释

托马斯说

  

默认为“not multi-threaded”,表示只能运行一个语句   在任何时候(每个数据库)。周围有一个同步块   发表声明。启用多线程时,则   synchronized语句在会话(连接)上而不是在   数据库对象。

     

选项是增加并发性,而不是吞吐量。默认   设置通常不是问题,除非你长时间运行   查询。

如果我理解正确就意味着当禁用时虽然h2可以接受多个连接,但它一次只能处理一个查询,但即使启用它,它也会在查询中途进行中途交换,但实际上仍然只是一次处理一个查询,即它可以开始处理query1,然后交换到query2,然后返回查询1 ectera,但实际上永远不会使用cpu来并行处理query1和query2。

所以在任何一种情况下,尽管在cpus之间切换,它只会在任何时候使用一个cpu。因此,如果您拥有一台功能强大的机器,例如16个内核,并且瓶颈是数据库,那么添加更多内核将无济于事因为h2只使用一个核心

这似乎是一个真正的限制,我想知道它与Derby或任何其他嵌入式java数据库的比较。

2 个答案:

答案 0 :(得分:0)

有些线程被阻止,可能是,是的,但我首先专注于那些被阻止的线程,这意味着消耗了CPU时间或磁盘I / O.这些是什么陈述?他们是不使用索引的查询吗?你有索引吗?或者你不必要地插入/删除行?另请参阅how to analyze performance problems上的文档。

答案 1 :(得分:0)

虽然我喜欢H2,但我认为这不是你的最佳选择。你应该尝试使用Derby,这是一个更加成熟和生产就绪(it's a descendant of the IBM product Cloudspace)。

然后,下一步是减少事务隔离。如果您看到this document了解每个隔离级别使用的锁类型。

由于您使用Hibernate,因此切换数据库不会花费太长时间(只需更改JDBC配置并将现有数据加载到新数据库中)。

就像H2一样,你可以嵌入Derby。