5

我正在创建一个数据库,并首先进行原型设计和基准测试。我正在使用 H2,一个开源的、商业免费的、可嵌入的、关系型的 Java 数据库。我目前没有对任何列进行索引。

数据库增长到 5GB 左右后,它的批量写入速度翻了一番(写入速度减慢了原来的 2 倍)。我每毫秒用一个新的、干净的数据库写大约 25 行,现在我写了 7GB 大约 7 行/毫秒。我的行由一个 short、一个 int、一个 float 和一个 byte[5] 组成。

我不太了解数据库内部结构,甚至对 H2 的编程方式也不太了解。我还想指出,我并不是在说 H2,因为这是我测试过的其他 DBMS 的问题。

如果没有索引开销,哪些因素可能会减慢这样的数据库速度?它主要与文件系统结构有关吗?根据我的结果,我假设 Windows XP 和 ntfs 处理文件的方式使得随着文件的增长将数据附加到文件末尾的速度变慢。

4

9 回答 9

2

这听起来很对。数据库性能通常会显着下降,因为数据不能再保存在内存中并且操作变得受磁盘限制。如果您使用普通的插入操作,并且想要显着提高性能,我建议在 H2 支持的情况下使用某种批量加载 API(如 Oracle sqlldr、Sybase BCP、Mysql 'load data infile')。这种类型的 API 绕过许多数据库子系统将数据直接写入数据文件。

于 2008-10-11T16:26:40.020 回答
2

随着数据库的增长,插入变得复杂的一个因素是表上的索引数量,以及这些索引的深度(如果它们是 B 树或类似的)。有更多工作要做,可能是您导致索引节点分裂,或者您可能只是从 5 级 B 树移动到 6 级 B 树(或更一般地说,从 N 到 N+1 级)。

另一个因素可能是磁盘空间的使用——如果您使用的是熟文件(大多数时候这是大多数人的正常类型;一些 DBMS 在 Unix 上使用“原始文件”,但您的嵌入式系统不太可能这样做,并且您会知道它是否这样做,因为您必须告诉它这样做),可能是您的较大表现在在磁盘上分散,导致性能下降。

如果问题出在 SELECT 性能上,那么可能还有许多其他因素也会影响系统的性能。

于 2008-10-10T22:15:24.013 回答
1

这很可能是由可变宽度字段引起的。我不知道 H2 是否允许这样做,但是在 MySQL 中,您必须创建具有所有固定宽度字段的表,然后将其显式声明为固定宽度字段表。这允许 MySQL 准确计算它需要在数据库文件中执行插入的位置。如果您不使用固定宽度的表格,则必须通读表格以找到最后一行的末尾。

追加数据(如果操作正确)是一个 O(n) 操作,其中 n 是要写入的数据的长度。它不依赖于文件长度,有查找操作可以轻松跳过。

于 2008-10-10T21:34:21.053 回答
1

对于大多数数据库,追加到数据库文件肯定比预先增长文件然后添加行要慢。查看 H2 是否支持预增长文件。

于 2008-10-10T21:47:24.990 回答
0

许多数据库引擎为每次更新创建一个隐式整数主键,因此即使您没有声明任何索引,您的表仍然会被索引。这可能是一个因素。

于 2008-10-11T22:00:00.567 回答
0

另一个原因是整个数据库是否保存在内存中,或者操作系统是否必须进行大量磁盘交换才能找到存储记录的位置。

于 2008-10-10T21:42:43.440 回答
0

我会把它归咎于 I/O,特别是如果您在具有普通硬盘的普通 PC 上运行数据库(我的意思是不在具有超快硬盘驱动器等的服务器中)。

于 2008-10-10T21:46:02.903 回答
0

你在执行增量提交吗?由于 H2 是一个符合 ACID 的数据库,如果您不执行增量提交,那么会有某种类型的重做日志,以便在某些意外故障(例如断电)或回滚的情况下,可以回滚删除。

在这种情况下,您的重做日志可能会变得很大并且内存缓冲区溢出,并且需要将您的重做日志以及您的实际数据写入磁盘,从而增加您的 I/O 开销。

于 2013-01-03T03:03:41.947 回答
0

从技术角度来看,将 H2 用于 7G 数据文件是错误的选择。如您所说,可嵌入。如果您需要存储这么多数据,您有什么样的“嵌入式”应用程序。

于 2009-10-06T20:03:54.847 回答