我已经通过hibernate为我的应用程序使用了h2 (1.3.172),在解决了一些非h2性能问题之后,我的性能瓶颈是h2。我的数据库非常简单,有10个表,每个表的容量也少于10万条记录,在h2功能范围内也是如此,但我认为问题在于多线程。
实际上,我使用hibernate/h2来控制我的应用程序中的内存消耗。我的应用程序使用管道方法处理文件,没有处理多少文件的限制,所以如果我将数据存储在内存中,我会快速地点击OutOfMemory。每个文件通常经历十个处理阶段,每个阶段都有自己的executor服务,当文件从一个阶段移动到另一个阶段时,它作为作业添加到相关的executor服务上。内存中存储的数据很少,因为作业是在执行器上启动的,有关文件的数据是从数据库中检索的,并且当作业完成时,数据被写回数据库。我们有十个具有机器核大小的线程池的执行者,因此在一个4台机器核上,理论上我们可以在任何时候有40个数据库请求,但更典型的是,我们的请求少于10个。因此,我们有许多事务同时进行,大部分涉及少量行。
我的应用程序是多线程的,如果我对它运行分析器,我发现大多数时候我的线程处于阻塞状态,等待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,但它似乎对我不起作用
关于在MultiCore系统中的使用
我刚读到关于MULTI_THREADED选项https://groups.google.com/forum/#!topic/h2-database/VoE3AU7mSuM的解释
托马斯说
默认情况是“非多线程”,这意味着在任何时候(每个数据库)只能运行一条语句。在运行语句时有一个同步块。当启用多线程时,同步语句就在会话(connection)上,而不是在数据库对象上。 该选项是增加并发性,而不是吞吐量。默认设置通常不是问题,除非您有长时间运行的查询。
如果我已经正确地理解了这一点,这意味着当禁用h2可以接受多个连接时,它一次只能处理一个查询,但即使启用了,它也会在查询之间切换一半,但实际上一次仍然只处理一个查询,也就是说,它可以开始处理query1,然后切换到query2,然后返回到查询1,但永远不会实际使用cpu并行处理query1和查询2。
因此,在这两种情况下,虽然在cpu之间切换,它将永远只使用一个cpu在任何时候。因此,如果您有一台功能强大的机器,例如16核,而瓶颈是数据库,那么在中添加更多的内核将毫无帮助,因为h2每次只使用一个内核,每次只使用吗?
这似乎是一个真正的限制,我想知道它与Derby或任何其他嵌入式java数据库相比如何。
发布于 2013-09-13 11:41:28
有一些线程被阻塞,这可能是,是的,但我首先要集中注意那些没有被阻塞的线程,这意味着正在消耗CPU时间或磁盘I/O。这些语句是什么?它们是不使用索引的查询吗?你有索引吗?还是不必要地插入/删除行?还请参阅关于如何分析性能问题的文档。
发布于 2013-09-13 11:50:27
虽然我喜欢H2,但我认为在您的情况下这不是最好的选择。您应该尝试Derby,这是一个更成熟和生产准备(它是IBM产品Cloudspace的后代)。
接下来的步骤是减少事务隔离。如果您看到每个隔离级别所使用的锁类型的本文件。
由于使用Hibernate,切换数据库不需要太长时间(只需更改JDBC配置并将现有数据加载到新数据库中即可)。
就像H2一样,您可以嵌入Derby。
https://stackoverflow.com/questions/18782331
复制相似问题