3

我一直在通过休眠将 h2 (1.3.172) 用于我的应用程序,在解决了一些非 h2 性能问题后,我的性能瓶颈是 h2。我的数据库非常简单,有 10 个表,每个表的卷少于 100,000 条记录,在 h2 功能范围内也是如此,但我认为问题出在多线程上。

我本质上是在使用 hibernate/h2 来控制我的应用程序中的内存消耗。我的应用程序使用管道方法处理文件,可以处理的文件数量没有限制,所以如果我将数据存储在内存中,我会很快点击 OutOfMemory。每个文件通常会经历十个处理阶段,每个阶段都有自己的执行器服务,当文件从一个阶段移动到另一个阶段时,它会作为作业添加到相关的执行器服务上。很少有数据存储在内存中,而是在执行程序上启动作业时从数据库中检索有关文件的数据,并在作业完成时将数据写回数据库。我们有 10 个执行器,每个执行器都有机器核心大小的线程池,所以在 4 个机器核心上,理论上我们可以随时向数据库发出 40 个请求,

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

我读到有一个 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 但它似乎根本不适合我

关于在多核系统中的使用

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

托马斯 说

默认值为“非多线程”,这意味着任何时候(每个数据库)只能运行一条语句。运行语句有一个同步块。启用多线程时,同步语句位于会话(连接)上,而不是数据库对象上。

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

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

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

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

4

2 回答 2

0

虽然我喜欢 H2,但我认为这不是您的最佳选择。您应该尝试 Derby,它更加成熟且可用于生产(它是 IBM 产品 Cloudspace 的后代)。

下一步是减少事务隔离。如果您看到此文档了解每个隔离级别使用的锁类型。

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

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

于 2013-09-13T11:50:27.520 回答
0

有些线程被阻塞了,可能是这样,但我会首先关注那些没有被阻塞的线程,这意味着它们正在消耗 CPU 时间或磁盘 I/O。那些是什么陈述?他们是不使用索引的查询吗?你有索引吗?或者您是否不必要地插入/删除行?另请参阅有关如何分析性能问题的文档。

于 2013-09-13T11:41:28.070 回答