Windowsで非常に大きな(800GB)テキストファイルの内容を並べ替える


25

各行に単語を含むテキストファイルがあり、ファイルのサイズは800GBです。単語をアルファベット順に並べ替える必要があります。

私は以下を使用してWindows ソートプログラムを使用しようとしました:

sort.exe input.txt /o output.txt

エラーが発生します:ソートを完了するのに十分なメインメモリがありません。

私は32GBのRAMを持っているので、ソートに10GBのメモリを指定しようとすると、

sort.exe input.txt /o output.txt /M 10000000

私は得る:

警告:指定されたメモリサイズは、使用可能なページングメモリに縮小されています。

入力レコードが最大長を超えています。より大きな最大値を指定します。

私のオプションは何ですか?



10
これはクロスポストではありません。私はマシンではないので、これをポストして他のポストを削除するには数分かかります!
マーヤン

3
将来的には、コミュニティが質問を移行できるようにします
-Ramhound

4
Linuxでは、この方法を適用できます。100Mbのファイルでは、大きな問題にはなりません。
エリックドゥミニル

3
使用しているWindowsのバージョンは何ですか?かなり古いWindows Server 2012 R2を使用したsort.exeは、ディスク上の一時ファイルを使用して(サイズ制限を文書化せずに)外部マージソートを実行できると主張しています。/ Tを使用して、一時ファイル用に800Gbの空きディスクを指定してみてください。また、「入力レコードが最大長を超えています」というメッセージはスペースとは無関係のようです-/ RECオプションを見て、ラインターミネータが何であるかを検討してください。
-davidbak

回答:


16

私のオプションは何ですか?

フリーウェアコマンドラインソートユーティリティCMSortをお試しください。

複数の一時ファイルを使用し、最後にそれらをマージします。

CMsortは、調整されたメモリに達するまで入力ファイルのレコードを読み取ります。次に、レコードがソートされ、一時ファイルに書き込まれます。これは、すべてのレコードが処理されるまで繰り返されます。最後に、すべての一時ファイルが出力ファイルにマージされます。使用可能なメモリが十分な場合、一時ファイルは書き込まれず、マージも不要です。

1人のユーザーが、130,000,000バイトのファイルをソートしたと報告しています。

自分でコードを微調整したい場合は、巨大なテキストファイルのソート-CodeProject-「利用可能なメモリを超えるサイズのテキストファイルの行をソートするアルゴリズム」もあります


26
うわー、130メガバイト!!! +1
デビッドフォースター

3
@DavidPostill Windows用のcoreutilsからのソートはより効率的ではありません--parallelか(複数のコアがある場合のオプション...)?
ハスター

23

もう1つのオプションは、ファイルをデータベースにロードすることです。EG MySQLおよびMySQL Workbench。
データベースは大きなファイルを扱うのに最適な候補です

入力ファイルに新しい行で区切られた単語のみが含まれている場合、これは難しくありません。

データベースとMySQL Workbenchをインストールしたら、これが必要です。
最初にスキーマを作成します(これは、引数値を増やすことでこれを変更できますが、単語が255文字より長くならないことを前提としています)。最初の列「idwords」は主キーです。

CREATE SCHEMA `tmp` ;

CREATE TABLE `tmp`.`words` (
  `idwords` INT NOT NULL AUTO_INCREMENT,
  `mywords` VARCHAR(255) NULL,
  PRIMARY KEY (`idwords`));

次に、データをインポートします。EGこれにより、すべての単語がテーブルにインポートされます(この手順は完了するまで時間がかかる場合があります。最初に小さな単語ファイルでテストを実行し、形式が大きい方(テーブルを切り捨てます。IEをクリアして、完全なデータセットをロードします)。

LOAD DATA LOCAL INFILE "C:\\words.txt" INTO TABLE tmp.words
LINES TERMINATED BY '\r\n'
(mywords);


このリンクは、ロードに適した形式を取得するのに役立つ場合があります。 https://dev.mysql.com/doc/refman/5.7/en/load-data.html
EG最初の行をスキップする必要がある場合は、次の手順を実行します。

LOAD DATA LOCAL INFILE "H:\\words.txt" INTO TABLE tmp.words
-- FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(mywords);

最後に、ソートされたファイルを保存します。これは、PCによっても時間がかかる場合があります。

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
INTO OUTFILE 'C:\\sorted_words.csv';

好きなように自由にデータを検索することもできます。EGこれにより、最初の50ワードが昇順(0番目または最初のワードから始まる)で表示されます。

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
LIMIT 0, 50 ;

頑張って
ピート


2
これは、ISかなりのマージンだけ正解。
MonkeyZeus

1
このアプローチは、特に、たとえば異なる順序でソートを再実行する必要があることがわかった場合は特に、より柔軟になります。
バーベキュー

MySQLMariaDB、または他のDBMSのインスタンスがどれほど高速であっても、同じマシンで実行されているSQLiteの挿入パフォーマンスに近づくことはありません。でもようなもので、高速としてSQLiteの最適なソリューションをソートし、最初の重複を削除することであるので、このデータ量は、(信頼は私が私が最初に試してみました!)が多すぎる(と遅い)プロセスにある、その後に挿入するDBなどのSQLiteの。そのため、この解決策は場合によっては有効かもしれませんが、私がやろうとしていることには当てはまりません。とにかくこれを投稿する時間を割いていただきありがとうございます。
マーヤン

注文mywordsは永遠にかかります。でも、LIMITMySQLはすべての値をすべて調べて順序付けする必要があるため、全体と同じくらい時間がかかりmywordsます。これを修正するには、完了後に以下を実行する必要がありますLOAD DATA。にインデックスを追加しますmywords。これで、その列で注文することができ、数千年かかることはありません。そして、あるあなたがテーブルを作成したデータをロードした後ではなく、一度に(はるかに高速データ・ロード)インデックスを追加した方が良いです。
バトルブトクス

7

sort

多くのアルゴリズムが注文されたファイルと注文されていないファイルを分類するのに使用されています[ 1 ]
これらのアルゴリズムはすべて既に実装されているため、テスト済みのプログラムを選択してください。

coreutilsの (すぎるウィンドウに利用可能なLinuxのが、から[ 2 ])、それが存在するsortマルチコアプロセッサの下で並行して実行することが可能なコマンドを:通常は十分です。

ファイルが非常に大きい場合は、分割split -lオプション(--parallel)、いくつかのチャンク内のファイル、おそらく並列オプション()を使用して、オプションで結果の順序付きチャンクソート-mmerge sort)することができます。
そのための多くの方法の1つをここで説明します(ファイルの分割、単一チャンクの順序付け、順序付けられたチャンクのマージ、一時ファイルの削除)。

ノート:

  • Windows 10には、Linux用のWindowsサブシステムと呼ばれるものがあり、Linuxのすべての例がより自然に見えます。
  • 異なるアルゴリズムを使用した並べ替えには、並べ替えられるデータエントリの数に応じて異なる実行時間があります(O(n m)、O(nlogn)...)。
  • アルゴリズムの効率は、元のファイルに既に存在する順序に依存します。
    (たとえば、バブルソートは、すでに順序付けられたファイル(正確にはN)の最も高速なアルゴリズムですが、他の場合には効率的ではありません)。

2

Peter Hの代替ソリューションを提供するために、テキストファイルに対してSQLスタイルのコマンドを許可するプログラムqがあります。以下のコマンドは、SQL Workbenchをインストールしたりテーブルを作成したりする必要なく、同じことを行います(ファイルと同じディレクトリのコマンドプロンプトから実行)。

q "select * from words.txt order by c1"

c1 列1の省略形です。

重複する単語を除外するには

q "select distinct c1 from words.txt order by c1"

出力を別のファイルに送信します

q "select distinct c1 from words.txt order by c1" > sorted.txt

これが800ギガファイルに対応するかどうかはわかりませんか?
ローリング

1
100%確信はありません-上記を1200行のファイル(9KB)でテストしました。開発者ページには、最大ファイルサイズについて何も言及していない「制限」ペー​​ジがあります。大きなファイルでもメモリの問題が発生する場合があります。
ブライアン

3
qがこのデータ量を処理できないことを覚えておいてくださいqが使用するSQLiteのを私はに直接データをロードできなかった場合はシーンの後ろのSQLiteをあなたが考えて作るもののq缶?
メイヤン

2

各行の単語が限られた語彙(英語など)からのものである場合、TreeMapと記録カウント(mは一意の値の数)を使用して、O(n + m log m)時間でリストをソートできます。

それ以外の場合は、Javaライブラリbig-sorterを使用できます。入力をソートされた中間ファイルに分割し、それらを効率的にマージします(全体的なO(nlogn))。ファイルをソートするには、次のようにします。

Sorter.serializerTextUtf8()
      .input(inputFile)
      .output(outputFile)
      .loggerStdOut() // display some progress
      .sort();

ランダムに生成された16文字の単語を含む1.7GBファイル(100m行)を作成し、142秒で上記のようにソートし、使用しているメソッドのO(n log n)計算の複雑さに基づいて、800GBの16文字単語を推定しますSSDを搭載したi5 2.3GHzラップトップでシングルスレッドのソートに約24時間かかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.