循环浏览和处理大型(10GB +)文本文件的最佳方法是什么?

Mar*_*ios 4 python mysql scripting parsing large-files

我需要遍历一个非常大的文本文件,大小为几GB(确切地说是一个区域文件)。我需要对区域文件中的每个条目运行一些查询,然后将结果存储在可搜索的数据库中。

目前,我选择的武器主要是Python和MySQL,这主要是因为据我所知。不过,我不确定这两种文件的处理效果如何。

在这方面有经验的人是否对打开和循环浏览文件而不会使我的系统超载的最佳方法有任何建议?打开文件(线程?)并存储处理后的数据后,最有效的处理文件方式如何?

Zac*_*oom 5

尽管您可能无法将整个数据库存储在内存中,但是在MySQL中存储该数量的数据应该没有真正的麻烦,因此请期待一些IO性能问题。与往常一样,在运行查询之前,请确保您具有适当的索引。

最重要的是不要尝试将整个文件加载到内存中。遍历文件,请勿尝试使用类似readlines的方法来立即加载整个文件。

确保批处理请求。一次加载几千行,并在一个大的SQL请求中将它们全部发送出去。

这种方法应该起作用:

def push_batch(batch):
    # Send a big INSERT request to MySQL

current_batch = []
with open('filename') as f:
    for line in f:
        batch.append(line)

        if len(current_batch) > 1000:
            push_batch(current_batch)
            current_batch = []

    push_batch(current_batch)
Run Code Online (Sandbox Code Playgroud)

区域文件通常采用正常格式,请考虑是否仅使用LOAD DATA INFILE就能摆脱困境。您可能还考虑创建一个命名管道,将部分格式的数据从python推入其中,并使用LOAD DATA INFILE通过MySQL读取它。

MySQL在优化插入方面有一些很棒的技巧,重点介绍:

  • 在每个插入语句中使用多个值列表。
  • 使用INSERT DELAYED,特别是如果您一次从多个客户端推送(例如使用线程)时,请使用。
  • 插入之前锁定表。
  • 调整key_buffer_size和bulk_insert_buffer_size。

最快的处理将在MySQL中完成,因此请考虑是否可以在数据存储在数据库中之后而不是之前就执行所需的查询。如果您确实需要使用Python进行操作,那么线程化将无济于事。一次只能执行一个线程的Python代码(GIL),因此,除非您做的事情花费大量的时间在C上,或者与外部资源进行接口,否则您将永远只能在一个线程中运行无论如何。

最重要的优化问题是速度的限制,如果数据库是限制因素,则毫无意义地绕开一堆线程来读取文件。真正知道的唯一方法是尝试并进行调整,直到它足够快地达到您的目的为止。