【问题标题】:sorting large text data对大文本数据进行排序
【发布时间】:2011-10-28 02:42:00
【问题描述】:

我有一个大文件(1 亿行制表符分隔值 - 大小约为 1.5GB)。根据其中一个字段对其进行排序的最快已知方法是什么?

我已经尝试过蜂巢。我想看看这是否可以使用 python 更快地完成。

【问题讨论】:

    标签: python sorting bigdata


    【解决方案1】:

    您是否考虑过使用 *nix sort 程序?用原始术语来说,它可能会比大多数 Python 脚本更快。

    使用-t $'\t' 指定它是制表符分隔的,-k n 指定字段,其中n 是字段编号,如果要将结果输出到新文件,则使用-o outputfile。 示例:

    sort -t $'\t' -k 4 -o sorted.txt input.txt
    

    将对input.txt的第4个字段进行排序,并将结果输出到sorted.txt

    【讨论】:

    • unix 排序命令确实是一个非常强大的工具。您可以控制要排序的字段格式(数字、日期等)以及程序可以分配的内存量,必要时执行拆分+合并排序。
    • alex 你能举个例子吗?排序程序本身需要相当长的时间……大约 40 分钟。这可能与内存分配或磁盘 IO 有关。我不确定如何找出瓶颈是什么,但我猜你的建议可能有用。
    • 上述解决方案中的一个错误:仅使用第二个字段,需要 -k 2,2 ...所以它不是零索引(至少在 Kubuntu 11.04 的排序版本中不是)。
    【解决方案2】:

    你想为文件建立一个内存索引:

    1. 创建一个空列表
    2. open文件
    3. 逐行读取(使用f.readline(),并在列表中存储一个包含要排序的值(使用line.split('\t').strip()提取)和文件中行的偏移量(您可以在拨打f.readline()之前拨打f.tell()获取)
    4. close文件
    5. sort名单

    然后打印排序后的文件,重新打开文件,对于列表中的每个元素,使用f.seek(offset) 将文件指针移动到行首,f.readline() 读取行,print 行.

    优化:您可能希望将行的长度存储在列表中,以便您可以在打印阶段使用f.read(length)

    示例代码(针对可读性而非速度进行了优化):

    def build_index(filename, sort_col):
        index = []
        f = open(filename)
        while True:
            offset = f.tell()
            line = f.readline()
            if not line:
                break
            length = len(line)
            col = line.split('\t')[sort_col].strip()
            index.append((col, offset, length))
        f.close()
        index.sort()
        return index
    
    def print_sorted(filename, col_sort):
        index = build_index(filename, col_sort)
        f = open(filename)
        for col, offset, length in index:
            f.seek(offset)
            print f.read(length).rstrip('\n')
    
    if __name__ == '__main__':
        filename = 'somefile.txt'
        sort_col = 2
        print_sorted(filename, sort_col)
    

    【讨论】:

    • 这是一个非常糟糕的想法 IMO。这样你就可以创建一个可以吃掉 8GB 或更多 RAM 的列表。 (一个python空字符串是40字节,将它乘以2,因为你想在这个元组中存储2个值,再乘以1亿——作者在问题中指定的行数)。问题的关键在于数据量很大......
    【解决方案3】:

    拆分成可以在内存中排序的文件。对内存中的每个文件进行排序。然后合并生成的文件。

    通过读取每个要合并的文件的一部分进行合并。每个文件的数量相同,为合并结果留出足够的内存空间。一旦合并保存这个。重复将合并数据块添加到文件中。

    这会最小化文件 i/o 并在磁盘上移动文件。

    【讨论】:

      【解决方案4】:

      我会将文件存储在一个良好的关系数据库中,在您感兴趣的字段上对其进行索引,然后读取订购的项目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-15
        • 2017-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-24
        相关资源
        最近更新 更多