将Squeryl和H2数据库用于桌面应用程序的性能问题

时间:2012-01-14 20:51:48

标签: database scala h2 squeryl

我有一个桌面应用程序,可以将其数据保存在本地H2数据库中。我正在使用Squeryl来连接数据库。

数据库的大小非常小(大约10kB)。我遇到了严重的性能问题,并且存在大量磁盘IO。我只是在阅读数据库,因此我希望可以缓存完整的数据;我甚至将缓存大小设置为某个值(高于总db大小的方式)。我也试过禁用锁定没有结果。

我的程序在数据库上执行很多小查询;基本上我有一个Swing TableModel,它对每个表项(每行的每一列)进行查询。我将每个调用包装成Squeryl transaction块。

我使用JVisualVM创建了一个配置文件,我怀疑以下调用树显示了问题。最顶层的方法是从我的代码读取访问权限。

link to JVisualVM screen shot.

问题

我该如何解决这个问题或者我做错了什么?不知怎的,我希望我能够对一个小到足以容纳1MB内存的数据库进行许多小调用。为什么这个磁盘IO会继续运行?如何避免它呢?

2 个答案:

答案 0 :(得分:3)

查看screeshot,您似乎是从TableModel的getValueAt()方法中的数据库中选择(调用堆栈顶部的方法名getRowAt()导致我的这个假设。)< / p>

如果我的假设是正确的,那么这是你的主要问题。 getValueAt()由JTable的paint()方法不断调用(可能是每秒几次),因此应该尽可能快。

您应该在单个SQL查询中获取JTable的数据,然后将结果保存在某个数据结构中(例如ArrayList或类似的东西)。

我不知道Squeryl,但我怀疑你真的需要将每个SELECT包装成一个事务。从堆栈跟踪看来,这会导致H2中的大量写入。您是否尝试在没有明确打开(和关闭)事务的情况下运行SELECT?

答案 1 :(得分:1)

最终解决方案非常简单。我引用常见问题解答。

延迟数据库关闭

通常,数据库在关闭它的最后一个连接时关闭。在某些情况下,这会降低应用程序的速度,例如,当无法保持至少一个连接打开时。可以使用SQL语句SET DB_CLOSE_DELAY <seconds>延迟或禁用数据库的自动关闭。参数<seconds>指定在最后一次连接数据库关闭后保持数据库打开的秒数。在最后一次连接关闭后,以下语句将使数据库保持打开状态10秒:

SET DB_CLOSE_DELAY 10

-1表示数据库未自动关闭。值0是默认值,表示最后一个连接关闭时数据库已关闭。此设置是持久性的,只能由管理员设置。可以在数据库URL中设置值:jdbc:h2:~/test;DB_CLOSE_DELAY=10