这里的环境: 我们为客户编写了一个基于嵌入式 h2 数据库的应用程序,在进行测试之前它已升级到最新版本。该数据库由 29 个表和 26 个视图组成。在 26 个视图中,只有 8 个在 java 中真正“使用”,映射视图休眠到 pojos。其他视图只是为其他视图进行背景计算,例如聚合一些值,然后按某些列分组。在这些视图中进行了大量计算。我们决定不使用 java 进行计算,因为您可以使用自己喜欢的工具(例如 h2 控制台)轻松检查数据库表,查看计算中是否有任何错误。由于这个事实,有很多“CASE WHEN ... END” 一旦该行中的单个列为 NULL,自休眠以来,这些视图中的语句总是返回所有列中具有 NULL 值的整行。我们也无法解决这个问题……然而,由于我们在计算中也有除法,我们需要检查 NULL、0 和 0.0。视图是“堆叠的”,因为有时会在其他地方使用一些中间值。但是总是有一个“堆栈”的 7 个视图“下方”一个最终视图也基于另一个使用 6 个视图的“堆栈”的视图。有些观点是相同的,有些则不同。
现在,问题来了: 当在“有趣的”表中向数据库中插入一对(比如 20 条)记录时,一个视图会在大约 400 毫秒。这对我们来说没问题。将数据扩展到大约 500-2000 条记录,特殊视图(交付大约 25 个聚合行)需要一个多小时 (1h) 来交付数据。该机器是具有 8GB RAM(-Xmx2G 和 -Xms1G)CPU 2.66GHz(Intel(R) Core(TM)2 Quad CPU Q8400 @ 2.66GHz)的 Linux 或具有 4GB RAM (-Xmx1G - Xms512m) CPU 未知,但可能是单核/双核@2GHz。
到目前为止我的分析: 我跟踪了应用程序的内存使用情况,这似乎不是主要问题。在长时间运行的查询期间查看堆栈跟踪显示,我的堆栈深度(有时)高达 100 级以下(!)我进入休眠 getEntityManager().createQuery(getCriteriaQuery()).getResultList() 的入口点。明显的“耗时”是 org.h2.table.TableFilter/Table/TableView.getBestPlanItem 和 org.h2.table.Plan.calculateCost 以及 org.h2.index.ViewIndex.getCost 。我检查了所有视图中的所有连接是否缺少索引,找到一个,添加了一个,但没有成功。
我的测试: 我将所有数据和模式转移到同一台 Linux 机器上的 PostgreSQL (8.1) 中(vanilla 未调整)并在那里运行测试(在进行任何 vaccuum 或 reindex 之前!)结果是压倒性的:大约。6 秒。对于具有相同数据的相同视图,在 h2 上花费了大约 1 小时。
现在我真的不想切换我的数据库,但这将是最终的选择,除非有人有一个好主意......
备注: 关于我发现的事情如下:在查看 h2 的 information_schema 中的视图时,我可以看到他正在做相当多的工作来分析视图本身。我的 sql 脚本中的所有视图都在 20 到 120 行之间(大约)。信息模式中的“编译”视图范围从 2KBytes 到 3MBytes(即兆字节),上面的一个接近 400k ...也许这也是问题的一部分...
好的,这就是所有的人。我很乐意提供任何帮助。我愿意切换数据库,因为我们到处都在使用 hibernate 和 CriteriaQuery,所以唯一的工作就是切换 jdbc 连接器,更改视图中的一些代码(已经完成,但必须在生产前检查两次)并安装PostgreSQL 或客户台式机 (irk) 上的 MSDE,这将导致可能发生的其他不需要的错误,因为 MS 更新可能会使 MSDE 损坏或数据库由于任何原因而无法启动......
问候,霍尔格