2011-08-16 20 views
8

我有一个大文件(1亿行标签分隔值 - 大小约1.5GB)。根据其中一个字段对此进行排序的最快速已知方法是什么?排序大型文本数据

我试过配置单元。我想看看这是否可以使用python更快地完成。

回答

16

您是否考虑过使用* nix sort程序?从根本上讲,它可能比大多数Python脚本更快。

使用-t $'\t'指定它的制表符分隔,-k n指定域,其中n是外地号码,-o outputfile如果你想将结果输出到一个新文件。 例子:

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

将在第4场排序input.txt,并把结果输出到sorted.txt

+0

unix排序命令的确是一个非常强大的工具。您可以控制字段的格式进行排序(数字,日期等)以及程序可以分配的内存量,并在必要时执行拆分+合并排序。 –

+0

亚历克斯你能举个例子吗?排序程序本身需要相当长的时间...大约40分钟。这可能与内存分配或磁盘IO有关。我不知道如何找出瓶颈是什么,但我猜你的建议可能有用。 – fodon

+1

以上解决方案中的一个错误:仅使用第二个字段,需要-k 2,2 ...因此它不是零索引(至少不是Kubuntu 11.04的排序版本)。 – fodon

1

我将文件存储在一个良好的关系型数据库,索引它在球场上你有兴趣,然后阅读订购的物品。

7

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

  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) 
3

分裂成可以在内存中排序的文件。将内存中的每个文件分类然后合并结果文件。

通过阅读每个要合并的文件的一部分进行合并。从每个文件中获得相同的数量,在合并结果的内存中留下足够的空间。一旦合并保存这一点。重复向文件中添加合并数据块。

这最大限度地减少了文件I/O并在磁盘上移动文件。