2011-08-08 2 views
1

私はいくつかの(1-5)非常に広い(〜50,000列).csvファイルを持っています。ファイルサイズは(.5GB〜1GB)(平均サイズは約500MB)です。あらかじめ指定された列のファイルに対して結合を実行する必要があります。もちろん、効率性が重要です。複数の結合列を効率的に使用できるようにスケールアウトできるソリューションは、現在は必要ありませんが、ボーナスです。ここに私の入力は、次のとおりです。C/C++を使用して、巨大なcsvファイル(1000×1000行)を効率的に結合するにはどうすればよいですか?

-Primaryファイル

- セカンダリファイル(複数可)

プライマリファイル(名前またはCOL位置。)二次ファイルの

-join列の

-join列(名前または列の位置)

-Left JoinまたはInner Join?マルチファイルの結果と

出力= 1つのファイルは、私はCベースの言語を使用して問題を解決するために探していますが、もちろんアルゴリズムのソリューションはまた、非常に参考になる

参加します。

+3

"Yikes"は私がこの1人に貢献できるものです... – Alex

+3

これを行うC++実装が既にあります:http://code.google.com/p/csvfix/ソースはダウンロード可能です。 – Cheesebaron

+0

あなたのCSVがシンプル(クォートなし、コンマがない)でLinuxの世界にいるなら、おそらくCコードを書く必要がないので、カット、ペースト、ソートすることができます。 – Arkadiy

答えて

1

CまたはC++を使用する必要がある場合は、ファイルを開いて、そのファイルをMySQLなどのデータベースに直接ロードします。 CおよびC++言語には、データを操作するための適切なデータテーブル構造や機能がありません。スプレッドシートアプリケーションは役に立ちますが、容量を処理できない場合があります。

つまり、私はフィールド(列)ごとにオブジェクトをお勧めします。フィールドのコレクションとしてレコード(ファイル固有)を定義します。ファイルから文字列にテキスト行を読み込みます。レコードに文字列からのフィールドデータをロードさせます。レコードをvectorに保存します。

宛先ファイルの新しいレコードを作成します。入力ファイルの各レコードについて、これらのフィールドを使用して新しいレコードをロードします。最後に、各レコードについて、各フィールドの内容を区切り文字で印刷します。

もう1つの方法は、2次元の文字列を拾い上げることです。

パフォーマンスのボトルネックはI/Oになります。あなたは、データの巨大なブロックを読み込みたいかもしれません。効率性の問題は、CSVファイルの可変レコード長です。

データベースを使用することをお勧めします。 MySQlのような無料のものがたくさんあります。

2

これまでのベスト・ベットはSqliteのようなもので、C++のバインディングがあり、それは素早く挿入や照会のために作られたテーラーです。

実際にデータを読み込むには、単に行ごとに行えば、Sqliteにフィールドを挿入することができます。オブジェクトをキャッシュで破棄する必要はありません)最適化として、1つのステートメント(insert into table(...) select ... union all select ... union all select ...)。

+0

SQLiteを使っているなら、 'SQLITE_MAX_COLUMN'がデフォルトで2000であることに気をつけて〜50k列の問題に遭遇するかもしれません。これはコンパイル時に最大32,767列まで設定できます。 https://sqlite.org/limits.html – captainpete

0

"参加"という言葉の意味によって異なります。ファイル1の列はファイル2の列と同じですか?その場合は、マージソートが必要です。ほとんどの場合、マージソートに基づく解決策は「ベスト」です。しかし、上記の@Blindyには、Sqliteのような既存のツールを使うべきだと私は同意します。そのような解決法はおそらく、列リストの変更に対する将来の証明です。

3

データベースを使用しない理由があるとすれば(私が知っている限り、50,000列はそのような理由があります)、歯をつかんで右のインデックスを作成するしかありませんファイル。順番にそれを読み取って、ハッシュテーブルに移入します。各エントリには、行全体が始まるファイル内のキー列とオフセットだけが含まれています。インデックス自体はメモリに快適に収まるものでなければなりません。十分なアドレス空間がある場合(つまり、32ビットアドレッシングが付いている場合を除きます)、実際のファイルデータをメモリマップして、適切な右の行にアクセスして出力する必要がありますのファイルを左に移動すると簡単にファイルになります。

+0

を参照してください。実際には、32ビットアーキテクチャでこれを行う予定です。私のユーザーは、合計32ビット以上、または2GB以上のRAMを持つことは期待できません。私は、結合/マージを実行するファイルが3つ以上あるので、各ファイルをメモリマップする必要があると思います。あなたはまだ私がアドレス空間を使い果たすことができると思いますか?それはメモリマッピングのポイントではありませんか? – Joel

+0

アドレスが不足していないかどうかは、mmappingのポイントになります。 5 GBをマッピングしている場合、アクセスしたいファイルのバイトを知るには、32ビットのアドレスにビットが足りないだけです。 32ビットアーキテクチャでは、通常は2GBのユーザースペースアドレスしか持たないでしょう。これはmmapを要求する前にすでにマップされているものから断片化することがあります。 1GBのファイルを1つでもmmapできるようになるかどうかは疑問です。メモリ内にインデックスを残しておくことはできますが、レコードを取得するにはファイル内で前後に検索する必要があります。 –

関連する問題