17

トラッカー、トレント、ピアに関するデータを含む最大300のテキストファイルがあります。各ファイルは次のように構成されています。

tracker.txt

time torrent
    time peer
    time peer
    ...
time torrent
...

トラッカーごとに複数のファイルがあり、情報の多くが繰り返されています(同じ情報、異なる時間)。

私が持っているものを分析し、次のようなものに関する統計を報告できるようにしたいと思います

  • 各トラッカーにあるトレントの数
  • トレントは何台のトラッカーにリストされていますか
  • トレントには何人のピアがいますか
  • ピアへの急流の数

膨大な量のデータがこれを私にとって困難にしています。これが私が試したことです。

MySQL

私はすべてをデータベースに入れました。エンティティタイプごとに1つのテーブルと、関係を保持するテーブル(たとえば、このトレントはこのトラッカー上にあります)。

データベースへの情報の追加には時間がかかりましたが(これを試したときは13 GBもありませんでした)、後で関係を分析するのは簡単ではありませんでした。やや複雑なクエリはすべて、完了するまでに24時間以上かかりました(あるとしても)。

クエリの例は次のとおりです。

SELECT COUNT(DISTINCT torrent) 
    FROM TorrentAtPeer, Peer 
    WHERE TorrentAtPeer.peer = Peer.id 
    GROUP BY Peer.ip;

ファイルのメモリ割り当てを増やしてみましたmy.cnfが、役に立たなかったようです。my-innodb-heavy-4G.cnf設定ファイルを使用しました。

編集:テーブルの詳細を追加する

これが私が使っていたものです:

Peer         Torrent                  Tracker        
-----------  -----------------------  ------------------  
id (bigint)  id (bigint)              id (bigint)
ip* (int)    infohash* (varchar(40))  url (varchar(255))
port (int)

TorrentAtPeer      TorrentAtTracker
-----------------  ----------------
id (bigint)        id (bigint)
torrent* (bigint)  torrent* (bigint)
peer* (bigint)     tracker* (bigint)
time (int)         time (int)

*indexed field. Navicat reports them as being of normal type and Btree method.
id - Always the primary key

外部キーはありません。既存のエンティティに対応するIDのみを使用できることに自信があり、外部キーチェックを追加することは不必要な遅延のように思われました。これはナイーブですか?

Matlab

これは、手間のかかる作業用に設計されたアプリケーションのように見えましたが、すべてのデータを一度に保持するのに十分なメモリを割り当てることができませんでした。

私は数値データを持っていなかったので、セル配列を使用していました。フットプリントを削減するために、これらの配列から試行に移りました。動作させることができませんでした。

Java

これまでの私の最も成功した試み。Limewireの人々によって提供されたPatriciaTriesの実装を見つけました。これを使用して、データを読み取り、所有している一意のエンティティの数を数えることができました。

  • 13トラッカー
  • 170万の急流
  • 32milピア

ピアでの急流の数の頻度を計算するのはまだ難しいと感じています。私は次のような試行を構築することによってそうしようとしています:

Trie<String, Trie<String, Object>> peers = new Trie<String, Trie<String, Object>>(...);
for (String line : file) {
    if (containsTorrent(line)) {
        infohash = getInfohash(line);
    }
    else if (containsPeer(line)) {
        Trie<String, Object> torrents = peers.get(getPeer(line));
        torrents.put(infohash, null);
    }
}

これまでにできたことから、このpeersトライを構築できれば、各ピアにあるトレントの数を簡単に見つけることができます。私は昨日それをすべて実行しました、そして私が戻ったとき、私はログファイルが書き込まれないことに気づきました、私^Zはアプリケーションとtime次のことを報告しました:

real 565m41.479s
user 0m0.001s
sys  0m0.019s

これは私には正しく見えませんが、ユーザーとシステムをそれほど低くする必要がありますか?また、JVMのヒープサイズを7GB(最大および開始)に増やしましたが、それがないと、メモリ不足エラーがすぐに発生します。

数時間/日待ってもかまいませんが、10時間くらいで止まるようです。

私の質問は、どうすればこのデータを分析できるかということだと思います。私が試したことは正しいことですか?足りないものはありますか?Javaソリューションはこれまでのところ最高のようですが、それを機能させるために私にできることはありますか?

4

4 に答える 4

6

MySQLクエリに時間がかかりすぎたとのことです。提出したリクエストの種類をサポートするために、適切なインデックスが設定されていることを確認しましたか?あなたの例では、それはのインデックスPeer.ip(またはネストされたインデックス(Peer.ip,Peer.id))とのインデックスになりTorrentAtPeer.peerます。

Javaの結果を理解しているように、データはたくさんありますが、異なる文字列はそれほど多くありません。したがって、各トラッカー、トレント、ピアに一意の番号を割り当てることで、時間を節約できる可能性があります。それぞれに1つのテーブルを使用し、IDとして文字列と数値の主キーを保持するインデックス値を使用します。そうすれば、これらのエンティティに関連するすべてのテーブルは、これらの数値を処理するだけで済み、スペースを大幅に節約し、操作を大幅に高速化できます。

于 2012-07-12T10:37:23.233 に答える
5

MySQLをもう一度試してみますが、スキーマは異なります。

  • ここではid-columnsを使用しないでください
  • ここで自然なプライマリキーを使用します:

    Peer:ip、port
    Torrent:infohash
    Tracker:url
    TorrentPeer:peer_ip、torrent_infohash、peer_port、time
    TorrentTracker:tracker_url、torrent_infohash、time

  • すべてのテーブルにinnoDBエンジンを使用する

これにはいくつかの利点があります。

  • InnoDBは、主キーにクラスター化インデックスを使用します。主キー列からのデータのみを要求する場合、追加のルックアップなしですべてのデータをインデックスから直接取得できることを意味します。したがって、InnoDBテーブルは多少インデックス編成されたテーブルです。
  • 代理キーを保存する必要がないため、サイズが小さくなります。->同じ結果のIOが少ないため、速度。
  • 自然な主キーと外部キーを使用するため、(高価な)結合を使用せずにいくつかのクエリを実行できる場合があります。たとえば、リンクテーブルには、ピアテーブルへの外部キーとしてTorrentAtPeer直接含まれています。peer ipサブネットワーク内のピアが使用するトレントをクエリする必要がある場合は、関連するすべてのデータがリンクテーブルにあるため、結合を使用せずにクエリを実行できるようになりました。

ピアごとのトレントカウントが必要で、結果にもピアのIPが必要な場合は、ここで自然な主キー/外部キーを使用するときにも利点があります。

スキーマを使用して、IPを取得するために参加する必要があります。

SELECT Peer.ip, COUNT(DISTINCT torrent) 
    FROM TorrentAtPeer, Peer 
    WHERE TorrentAtPeer.peer = Peer.id 
    GROUP BY Peer.ip;

自然な主キー/外部キーの場合:

SELECT peer_ip, COUNT(DISTINCT torrent) 
    FROM TorrentAtPeer 
    GROUP BY peer_ip;

編集 まあ、元の投稿されたスキーマは実際のものではありませんでした。これで、Peerテーブルにportフィールドがあります。ここで主キー(ip、port)を使用し、id列を削除することをお勧めします。これは、リンクテーブルに複数列の外部キーが必要であることも意味します。答えを調整しました...

于 2012-07-12T11:50:00.240 に答える
0

C ++を使用できる場合は、Boostflyweightを確認する必要があります。

flyweightを使用すると、文字列があるかのようにコードを記述できますが、文字列の各インスタンス(トラッカー名など)は、ポインターのサイズのみを使用します。

言語に関係なく、メモリを節約するためにIPアドレスをintに変換する必要があります(この質問を参照してください)。

于 2012-07-12T14:20:23.073 に答える
0

ほとんどの場合、NOSQLと分散テクノロジーで解決できる問題があります。

i)Hadoop/HBaseを使用して分散システムを作成します。

ii)数十/ 100台のAWSマシンをレンタルしますが、数秒間だけです(それでも0.50ドル未満の費用がかかります)

iii)利益!!!

于 2012-07-12T17:53:25.763 に答える