如何避免连接Access数据库时出现“内存不足”错误?

4
我有一个本地的MS Access数据库,我正在尝试通过Java连接它。我使用UCanAccess作为JDBC驱动程序,虽然数据库已经链接到一个受密码保护的网络驱动器上的数据库,但我要连接的数据库已经过验证,并且没有自己的密码保护。我在类路径中拥有所有依赖项。连接时,我一直收到以下错误:

java.lang.OutOfMemoryError: Java heap

我启动了Java VisualVM,确实,主线程正在使用分配的2GB内存。这只发生在我尝试从大型MySQL数据库中选择大量记录时。我在Google上找不到任何与此连接相关的结果,因为我甚至没有尝试查询数据库。
代码非常简单:
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
System.out.println("Initiating connection...");
conn = DriverManager.getConnection("jdbc:ucanaccess://C:/Databases/StoreSalesCurrent.accdb");
System.out.println("Connection established");
conn.close();

任何想法为什么尝试建立连接会导致如此大的内存消耗?

我的女朋友也尝试过这个,虽然她没有遇到这个特定的错误,但是她无法让JDBC驱动程序与MS Access配合使用。她尝试的驱动程序只是为了证明可能性而存在,并不是真正意义上的使用。此外,在Java 8中,她使用的驱动程序已经不再起作用,因为桥接使用的特定方法已被删除。我不确定你的代码是否也是如此。我的女朋友最终放弃了MS Access并开始使用postgresql数据库。 - Taelsin
1
@Taelsin - UCanAccess是一种纯Java解决方案,不使用JDBC-ODBC桥,在Java 8下运行良好。 - Gord Thompson
1
@TheDankOG - 请尝试将 ;memory=false 添加到您的连接 URL 中,看看是否有帮助。 - Gord Thompson
1个回答

3
默认情况下,UCanAccess在JVM生命周期的第一个连接中将整个数据库加载到内存中。选择此默认行为是因为典型的使用情况是较小的个人数据库,而不是占用几十GB的大型数据库。如果设置适当的连接参数(例如,设置memory=false和其他相关选项),它将正常工作,但JVM生命周期中的启动时间可能会变长。有关更多详细信息,请参见UCanAccess网站

数据库不是2GB,而是大约1.1GB,这就是为什么我分配了2GB给JVM的原因,以便它可以加载整个数据库并为查询执行提供一些额外的空间。我会在有机会时尝试那个memory=false标志。编辑:连接需要很长时间,但至少在JVisualVM中堆没有爆炸。 - TheDankOG
在内存=false之前,您可能希望使用Skipindexes=true来最小化内存占用(它不会影响引用完整性约束)。实际上,意外的内存占用可能是由于索引造成的,但如果您可以使用memory=true,则会在查询执行中获得良好的性能体验。 - jamadei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接