Java HyperSQL(HSQLDB):大规模插入性能

Java HyperSQL(HSQLDB):大规模插入性能,java,performance,hsqldb,bulkinsert,Java,Performance,Hsqldb,Bulkinsert,我有一个应用程序,它必须将大约1300万行大约10个平均长度的字符串插入到嵌入式HSQLDB中。我一直在调整(批量大小、单线程/多线程、缓存/非缓存表、MVCC事务、日志大小/无日志、定期调用检查点等),但在16核、12 GB的机器上仍然需要7小时 我之所以选择HSQLDB,是因为我认为如果我充分利用所有这些核心,我可能会获得可观的性能提升,但我开始怀疑我的决定 有人能给我看一下银弹吗?检查你的应用程序在做什么。第一件事是查看taskmanager(或特定于操作系统的类似工具)和visualvm

我有一个应用程序,它必须将大约1300万行大约10个平均长度的字符串插入到嵌入式HSQLDB中。我一直在调整(批量大小、单线程/多线程、缓存/非缓存表、MVCC事务、日志大小/无日志、定期调用检查点等),但在16核、12 GB的机器上仍然需要7小时

我之所以选择HSQLDB,是因为我认为如果我充分利用所有这些核心,我可能会获得可观的性能提升,但我开始怀疑我的决定


有人能给我看一下银弹吗?

检查你的应用程序在做什么。第一件事是查看taskmanager(或特定于操作系统的类似工具)和visualvm中的资源利用率

导致不良绩效的优秀候选人:

  • 磁盘IO
  • 垃圾收集器
可能会使您的性能略优于HSQLDB(同时保持语法兼容性)

在任何情况下,您都可能希望尝试使用更高的延迟来同步到磁盘,以减少随机访问磁盘I/O。(即
SET WRITE\u delay

希望您正在执行批量
INSERT
语句,而不是每行一次插入。如果没有,尽可能这样做

根据您的应用程序需求,使用键值存储可能比使用RDBMS更好。(您是否需要定期插入1.3*10^7个条目?)


您的主要限制因素将是对磁盘的随机访问操作。我非常怀疑你所做的任何事情都会受到CPU的限制。(看一下<代码>顶部/代码>,然后将它与<代码> iOTP> <代码> < /p> 用这么多的记录,也许你可以考虑切换到一个NoSQL的DB。当然,这取决于需要存储的数据的性质/格式。

对于缓存表,磁盘IO占用了大部分时间。不需要多个线程,因为您要插入到同一个表中。显著提高性能的一件事是重用单个参数化PreparedStation,为每个行插入设置参数

在您的机器上,通过对内存映射IO使用较大的NIO限制,可以显著提高IO。例如
设置文件NIO大小8192
。需要64位JVM才能使较大的大小产生效果

要在大容量插入期间减少IO,请使用
将文件日志设置为FALSE
,并且在插入结束之前不要执行检查点。详情如下:

更新:下面1600万行的插入测试生成了一个1.9GB的.data文件,在一个平均2核处理器和7200RPM磁盘上只需几分钟。关键是大型NIO分配

connection time -- 47
complete setup time -- 78 ms
insert time for 16384000 rows -- 384610 ms -- 42598 tps
shutdown time  -- 38109 

我要冒险猜测一下(不是HSQLDB专家),然后说主阻止程序在你的IO(磁盘)上。是的,我想这是因为CPU的百分比并不是很高。从多个线程执行批插入有什么好处吗?在这种情况下,我应该坚持使用单个线程吗?可能没有,除非您可以实现基于SSD的解决方案。这是在什么操作系统上进行的?我发现,在OSX上,大批量插入相当快,而在Windows上(在各种硬件配置上)则慢得令人沮丧。在2007年年中的Mac Mini上使用内置硬盘插入108000行大约需要1分钟。在新型非虚拟化Windows服务器上大约需要15分钟,而在旧的2006非虚拟Dell 750 Windows服务器上则需要更长的时间(大约20分钟后取消)。没关系,问题与索引相关。当我添加一个索引时,问题就解决了。