2011-08-16 53 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並在磁盤上移動文件。