Database 是什么减缓了数据库性能的增长?

Database 是什么减缓了数据库性能的增长?,database,batch-file,insert,scalability,Database,Batch File,Insert,Scalability,我正在创建一个数据库,首先是原型设计和基准测试。我使用的是H2,一个开源的、商业上免费的、可嵌入的、关系型的java数据库。我目前没有在任何列上建立索引 数据库增长到5GB左右后,其批写入速度翻了一番(写入速度比原始速度慢了2倍)。我用一个新的、干净的数据库大约每毫秒写25行,现在在7GB的速度下,我大约每毫秒写7行。我的行由一个short、一个int、一个float和一个byte组成[5] 我不太了解数据库内部,甚至不知道H2是如何编程的。我还想指出,我并不是在说H2的坏话,因为这是我测试过的

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

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

我不太了解数据库内部,甚至不知道H2是如何编程的。我还想指出,我并不是在说H2的坏话,因为这是我测试过的其他DBMS的一个问题


如果没有索引开销,哪些因素可能会像这样降低数据库的速度?它主要与文件系统结构有关吗?根据我的结果,我假设windows XP和ntfs处理文件的方式会使在文件增长时向文件末尾追加数据的速度变慢

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


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

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

我将其归咎于I/O,特别是如果您在普通PC上使用普通硬盘运行数据库(我的意思是不在具有超高速硬盘驱动器的服务器上),则对大多数数据库而言,附加到数据库文件肯定比预增长文件然后添加行要慢。查看H2是否支持文件的预增长。

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

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


如果问题出在“选择性能”上,可能还有许多其他因素也会影响系统的性能。

这听起来不错。数据库性能通常会显著下降,因为数据不能再保存在内存中,操作会绑定到磁盘。如果您使用的是正常的插入操作,并且希望显著提高性能,我建议如果H2支持,使用某种批量加载API(如Oracle sqlldr、Sybase BCP、Mysql“加载数据填充”)。这种类型的API绕过许多数据库子系统直接将数据写入数据文件。

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

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

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


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

我忘了提到我的byte[5]字段实际上位于blob字段(可变长度字段)中。这可能与此有关。谢谢你们的快速回复,所有人。不管这是否是个问题,听起来预先培养它是个好主意。谢谢有趣的是,我没有想到文件会在整个磁盘上被分割,但是我想如果它有那么大的话,它一定会被分割!