Python: 数百万小文件读写速度慢

16 投票
7 回答
13015 浏览
提问于 2025-04-15 23:54

结论: 看起来HDF5是我需要的解决方案。简单来说,"HDF5是一种数据模型、库和文件格式,用于存储和管理数据。" 它的设计目标是处理大量数据。它还有一个叫做python-tables的Python模块。(下面的回答里有链接)

HDF5在保存海量数据方面的表现好得多,效率提升了1000%。不过,从2亿行数据中读取或修改数据还是挺麻烦的,这就是下一个需要解决的问题。


我正在构建一个目录树,里面有很多子目录和文件。大约有1000万个文件分布在十万个目录中。每个文件最多有32个子目录。

我有一个Python脚本来构建这个文件系统,并读取和写入这些文件。问题是,当文件数量超过一百万时,读取和写入的速度变得非常慢。

这是我用来读取文件内容的函数(文件里包含一个整数的字符串),它会在这个整数上加上一个特定的数字,然后再写回原文件。

def addInFile(path, scoreToAdd):
    num = scoreToAdd
    try:
        shutil.copyfile(path, '/tmp/tmp.txt')
        fp = open('/tmp/tmp.txt', 'r')
        num += int(fp.readlines()[0])
        fp.close()
    except:
        pass
    fp = open('/tmp/tmp.txt', 'w')
    fp.write(str(num))
    fp.close()
    shutil.copyfile('/tmp/tmp.txt', path)
  • 关系型数据库在访问这些数据时似乎太慢了,所以我选择了文件系统的方法。
  • 我之前尝试用Linux命令行来处理这些,但速度慢得多。
  • 我先把文件复制到一个临时文件,然后再访问和修改它,最后再复制回去,因为我发现这样比直接访问文件要快。
  • 把所有文件放在一个目录里(使用reiserfs格式)在访问时导致了太大的延迟。

我认为变慢的原因是文件数量太多。这个函数执行1000次的时间还不到一秒,但现在却要花1分钟。

你有什么建议可以解决这个问题吗?我需要改变我的目录树结构吗?

我只需要快速访问这个庞大文件池中的每个文件*

7 个回答

5

我建议你重新考虑一下你的方法,使用很多非常小的文件肯定会导致严重的性能问题。根据你程序的目的,使用某种数据库可能会更高效。

如果你需要频繁读写数据,你也可以考虑增加硬件,比如使用固态硬盘(SSD)或者把所有数据放在内存里(可以是直接放或者通过缓存)。仅仅依靠传统硬盘,在这种情况下是很难获得好的性能的。

我自己没用过,但比如说Redis就是一个持久化的键值存储,听说速度非常快。如果你的数据适合这种模型,我绝对会尝试这个或者类似的东西。你可以在这篇文章中找到一些性能数据,这样可以让你了解可以达到什么样的速度。

6

有两个建议:

第一,如果你的文件夹结构有32层子目录,那这个设计本身就是有问题的。假设你真的有“约1000万个文件”,那么只用一层子目录就足够了(前提是你使用的是现代的文件系统)。

第二:你说你有“约1000万个文件”,而且每个文件“包含一个整数字符串”。假设这些整数是32位的,并且你直接存储它们而不是作为字符串,那么总的数据大小大约是40MB(1000万文件 * 每个文件4字节)。假设每个文件名是32字节,再加上320MB的“键”数据。

所以你可以轻松地将整个数据集放入内存中。我建议你这样做,并在主内存中处理这些数据。而且,除非你有特别的理由需要复杂的目录结构,否则我还建议把数据存储在一个文件里。

8

我知道这不是直接回答你的问题,但它确实能解决你的困扰。

你需要研究一下类似于 HDF5 的东西。这个工具专门用来处理那种有很多层次的数据,里面可能有数百万个数据点。

你真的很幸运,因为有一个很棒的Python库可以用来操作HDF5,叫做 pytables。我也用过类似的方法,效果非常好。

撰写回答