为什么在硬件相同的不同机器上读取SQLite数据库速度较慢?

3
好的,我注意到一些行为是“意外”的,我很好奇是否有人能够提供任何见解,了解到底发生了什么。我会尽量简洁地说明...
我有一个sqlite数据库,我正在使用Python(150k行,11个表)访问它,用于神经网络训练。目的不重要,但这意味着我的数据点作为相当大的blob存储在一个表中,而且DB大约为5GB。因为我只拉取某些行(由于交叉验证或其他过滤方式),我发现在某些有意义的列上索引会导致速度显著提高。当天气晴朗时,我可以在约2秒钟内选择、获取和格式化约500个数据点。这很好。
然而,正如任何熟悉神经网络/反向传播/SGD的人所知道的那样,这个过程可能需要很长时间,具体取决于数据和架构。为了最优地并行化事情,我已经调配了多台机器(Mac Pro,8GB RAM,16个核心,速度不知道多少)在不同的线程下启动不同条件的训练场景。由于内存限制,上限约为6或7个单独的线程,每个线程都访问相同的数据库文件。现在,据我所知,这些机器是相同的。
这里就变得奇怪了。起初,在我的基准机上性能非常出色,而并行线程数从未使事情变慢(一个线程与七个线程基本相等)。当我第一次将这个数据库文件复制到其他机器上(并重新创建我的索引)时,其中一个与我的基准机一样快,但另一个却慢了两倍。我当时认为这是硬件差异,并继续过着我的生活。然后,修改sqlite数据库并将其重新复制到所有机器上后,它现在在以前慢的机器上很快,而所有其他机器都显示出较慢的性能,包括基准机。
我不明白。我对所有实例做了同样的事情。复制时数据库文件是相同的,然后我删除/创建相同的索引,因为我很确定sqlite索引是指磁盘上的绝对位置。我在unix环境中,所以文件碎片不应该是罪魁祸首(对吗?)。在某些配置中,并发似乎不是问题,而在其他情况下则会导致瓶颈。此后,我检查了机器,发现它们在纸面上实际上是相同的。最令我困惑的部分是,性能在单个机器的配置中存在差异。
我真的很无助。任何方向都将不胜感激。我绝对不精通关系数据库编程,但我已经没有更多的想法了。
更新: 我可能已经“解决”了我的问题,但这个问题还没有得到解答。我发现如果我基本上为每个系统重新启动数据库文件,最终我会让性能在所有机器上相等。这个过程大致是...
    while unhappy:
 1. Drop all indexes
 2. Create new indexes
 3. Make a handful of select/fetch calls
 4. Commit / quit / restart

一段时间后,它似乎会稳定下来,变得令人满意。不过我不知道为什么。


硬盘驱动器在硬件和内容方面是否完全相同? - Tim
2
SQLite主要受I/O限制,因此您可能会看到文件系统差异的影响(例如,SQLite文件可能被放置在硬盘上的不同位置)。由于您只有5GB,您可以尝试将整个数据库放入内存中(通过:memory:),以摆脱对磁盘的依赖。 - schlenk
你是否排除了其他同时访问磁盘的程序?例如备份、防病毒软件、下载更新等会导致磁盘访问,从而增加 SQLite 请求的延迟。 - Roger Binns
@Tim:硬件方面,是的 - 就制造而言。内容方面,它们有相当可比的空间。 - Eric Humphrey
@schlenk: 当我刚开始这些花招时,我最初是在内存中进行所有操作的。后来我切换到一个合适的数据库后端,这样我就能够实现线程安全的磁盘输入/输出,因为我希望能在并发线程中运行多个训练会话...我猜想内存数据库无法在不同进程之间共享吧?内存一度成为我的瓶颈,而现在似乎磁盘访问成为了新的问题。我曾考虑过磁盘分配的唯一性,但是希望重新索引能够解决问题。 - Eric Humphrey
@RB:是的,我正在关闭所有东西...甚至通过ssh / screen远程启动所有东西,所以它将所有时间都花在Python线程上。 - Eric Humphrey
2个回答

2
如果您没有使用auto_vacuum=FULL运行数据库,那么可能会在数据库文件中存在一些数据结构的碎片化。您是否尝试过在数据库上运行VACUUM?(点击此处了解详情)请注意保留HTML标签。

我打算继续说这可能就是答案了。虽然我仍然不完全确定内部发生了什么,但运行清理程序似乎确实有所帮助。没有准备好它需要几分钟的时间,但是... 胜利就是胜利。 - Eric Humphrey

0

好的。如果是这样的话,我建议首先进行系统基准测试,并查看测试结果。我的猜测是它们(在性能上)不会相等。 - Ophidian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接