C/C++的数据库写入与磁盘I/O

Database Write vs. Disk I/O For C/C++

本文关键字:磁盘 C++ 数据库      更新时间:2023-10-16

所以我正在为一个新项目生成工作流。在第一阶段,将有一个生成大量数据的C/C++代码(基于测试用例的二进制文件格式,大约1TB)。然后,这些数据将被导入数据库,以便与驻留在那里的另一个数据集进行比较。

我的问题是,打开数据库软件的端口并直接写入,还是磁盘写入许多小文件(约10亿)并稍后导入数据库会更快?C代码将在有时间限制的集群上运行,因此需要快速完成。

虽然正确答案应该是"取决于情况,您需要测量",但在这种情况下,可以给出具有可接受确定性的不合格答案:

与数据库服务器直接对话几乎肯定会更快。

原因不仅在于先写入磁盘,然后在通过网络发送数据之前再次读取数据,这涉及到磁盘驱动器的额外延迟和带宽限制(这是不可避免的,因为每个文件在页面缓存中至少占用一个页面,十亿个文件——即使每个文件只有1字节的内容——也需要至少4TiB的缓冲区,因此不会有缓存)。假设在快速磁盘上按顺序读取,读取4TiB的数据需要3-5个小时。虽然由于延迟写回,向磁盘写入实际上可能主要是按顺序进行的,但在发送数据之前再次读取数据几乎可以保证不会是连续的(而且不存在提前读取的情况,这对于不同的文件来说是不可能的)。如果幸运的话,有些操作可能仍然是重叠的,隐藏了它们的延迟——但总的来说,这并不是"免费的"。

虽然确实,您可能会受到数据库接受请求的能力或网络带宽的限制,但这是您总是受到的限制,即使您没有添加额外的副本,至少前者是您可以很容易地优化的。您可以在没有任何索引的情况下将数据插入数据库,这将非常快速。然后,数据库服务器可以创建您以后可能需要的任何incides。当然,这可能需要一些时间,但这可能比每次更新指数快一个数量级(此外,谁在乎呢,如果重要的是你的限时工作完成得快的话)。

然而,更重要的是,仅仅打开、关闭和重新打开十亿个文件就需要非常显著的时间(这包括遍历目录层次结构、名称到索引节点的转换和访问检查等),而且访问单个文件所花费的时间将是非常疯狂的。即使在没有物理"查找"的固态磁盘上,随机访问时间也不是"零"(它们要小得多,但0.1毫秒乘以10亿仍然是几乎3个小时在查找上的额外花费!)。

您没有指定正在运行的数据库,所以理论上答案可能是任何东西。然而,在实践中,现代硬盘驱动器速度较慢:它们的写入速度约为100MB/s。通常,如果要向数据库中插入大量数据,这是一个限制因素。计算机中的RAM没有帮助,因为1TB无法放入RAM。但是,您可能需要使用特定于数据库的技巧,例如在单个事务中添加所有数据,以及可能编译一次并调用多次的预处理查询。如果你使用的是固态硬盘,答案可能会有所不同,但这取决于固态硬盘的速度。

请注意,网络接口可能会限制添加性能。千兆位链路实际上意味着略低于125 MB/s。因此,如果您的数据库在另一台计算机上,则网络接口性能可能是限制因素。然而,如果您在同一台计算机上或使用万兆链路生成数据,那么网络链路性能不太可能成为限制因素。

然而,唯一确定的答案是在你的环境中进行测试。如果绩效对你来说很重要,一定要学习基准测试的艺术。

这张表有索引吗?如果是这样的话,那么先插入数据,然后在插入所有数据后才构建索引可能会提高性能。

您必须对此进行测试才能知道。

不同的数据库产品以不同的速度运行,我们不知道数据库的硬件,如果在真正的大数据上有很多索引,可能会让一切变得缓慢。