所以我正在为一个新项目生成工作流。在第一阶段,将有一个 C/C++ 代码生成大量数据(大约 1TB 基于测试用例的二进制文件格式)。然后,该数据将被导入数据库,以便与将驻留在那里的另一个数据集进行比较。
我的问题是打开数据库软件的端口并直接写入那里或磁盘写入许多小文件(约 10 亿)并稍后导入数据库会更快吗?C 代码将在时间有限的集群上运行,因此需要快速完成。
您没有指定您正在运行的数据库,所以理论上答案可能是任何东西。然而,实际上现代硬盘驱动器很慢:它们以大约 100 MB/s 的速度写入。通常,如果您将大量数据插入数据库,这是限制因素。计算机中的 RAM 无济于事,因为 1TB 不适合 RAM。但是,您可能需要使用特定于数据库的技巧,例如在单个事务中添加所有数据,以及可能需要编译一次并多次调用的预处理查询。如果您使用的是固态硬盘 (SSD),答案可能会有所不同,但这取决于 SSD 的速度。
另请注意,网络接口可能会限制附加性能。千兆链路实际上意味着略低于 125 MB/s。因此,如果您的数据库位于另一台计算机上,则网络接口性能可能是限制因素。但是,如果您在同一台计算机上生成数据或使用 10 Gb 链路,则网络链路性能不太可能成为限制因素。
然而,唯一确定的答案是在您的环境中对其进行测试。如果性能对您很重要,请学习基准测试的艺术。
表有索引吗?如果是这样,那么首先插入数据并仅在插入所有数据后才构建索引可能会提高性能。
虽然正确的答案应该是“取决于,你需要衡量”,但在这种情况下,可以以可接受的确定性给出不合格的答案:
直接与数据库服务器对话几乎肯定会更快。
原因不仅在于首先写入磁盘,然后在通过网络发送数据之前再次读取数据,这涉及来自磁盘驱动器的额外延迟和带宽限制(这是不可避免的,因为每个文件至少占用一页页面缓存,十亿个文件——即使每个文件只有 1 个字节的内容——至少需要 4TiB 的缓冲区,所以不会有缓存)。假设在快速磁盘上连续读取,读取 4TiB 数据需要 3-5 小时。虽然由于延迟写回,实际上可能主要按顺序写入磁盘,但在发送数据之前再次读取数据几乎可以保证不连续(并且不会发生预读这样的事情,对于不同的文件是不可能的)。如果幸运的话,一些操作可能仍然会重叠,
虽然您可能会受到数据库接受请求的能力或网络带宽的限制,但这是您始终受到限制的东西,即使您不添加额外的副本,至少前者是您的东西可以相当容易地优化。您可以在没有任何索引的情况下将数据插入数据库,这将非常快。然后,数据库服务器可以创建您以后可能需要的任何 incides。这当然可能需要一些时间,但它可能比每次更新时更新索引快一个数量级(此外,谁在乎,如果重要的是你的限时工作快速完成)。
然而,更重要的是,仅打开和关闭以及重新打开十亿个文件就需要非常显着的时间(这涉及遍历目录层次结构、名称到 inode 的转换以及访问检查等),以及花费的时间量访问单个文件将非常疯狂。即使在没有发生物理“搜索”的固态磁盘上,随机访问时间也不是“零”(它们要小得多,但 0.1 毫秒乘以 10 亿仍然几乎是 3 小时的额外搜索时间!)。
您必须对此进行测试才能知道。
不同的数据库产品以不同的速度运行,我们不知道数据库的硬件,如果在真正的大数据上有很多索引,它可能会使一切变慢。