0

ここで質問しました。簡単に言えば、私のアルゴリズムには 4 次元配列が必要です。サイズは32Gに達する可能性があります。MongoDBに保存する予定です。私は私の方法でそれを実装しました。これまで MongoDB を使用したことがないため、実装が遅すぎます。この 4 次元配列を MongoDB に格納するにはどうすればよいですか?

いくつかの統計:

アレイのサイズは約 12*7000*100*500 で、サーバーは 16.0GB の RAM を搭載した Windows Server 2008 R2 Standard であるため、アレイ全体を更新するには数時間 (待っていなかったので、10 時間以上かかると思います) かかります。 cpu は Intel(R) Xeon(R) CPU、2.67GHz です。私のmongoDBのバージョンは2.4.5です

私の実装を少し説明してください。 私の配列には 4 つの次元があり、それぞれ z、d、wt、wv という名前を付けます

まず、配列要素の文字列を作成します。たとえば、配列要素 p_z_d_wt_wv[1][2][3][4] を取ります。z は 1、d は 2、wt は 3、wv は 4 であるため、文字列「1_2_3_4」を取得します。これは p_z_d_wt_wv[ 1][2][3][4].次に、p_z_d_wt_wv[1][2][3][4] の値をデータベースに保存します。だから私のデータは以下のようになります:

{ "_id" : { "$oid" : "51e0c6f15a66ea5c32a99773"} , "キー" : "1_2_3_4" , "値" : 113.1232}

{ "_id" : { "$oid" : "51e0c6f15a66ea5c32a99774"} , "キー" : "1_2_3_5" , "値" : 11.1243}

アドバイスをいただければ幸いです。

よろしくお願いします!

以下は私のコードです

public class MongoTest {

    private Mongo mongo = null;
    private DB mmplsa;
    private DBCollection p_z_d_wt_wv;
    private DBCollection p_z_d_wt_wv_test;
    public void init()
    {
        try{
        mongo = new Mongo();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (MongoException e) {
            e.printStackTrace();
        }

        mmplsa = mongo.getDB("mmplsa");
        p_z_d_wt_wv = mmplsa.getCollection("p_z_d_wt_wv");    
    }

    public void createIndex()
    {
        BasicDBObject query = new BasicDBObject("key",1);
            p_z_d_wt_wv.ensureIndex(query,null, true);
    }

    public void add( String key, double value)
    {
        DBObject element = new BasicDBObject();
        element.put("key", key);
            element.put("value", value);
        p_z_d_wt_wv.insert(element);
    }

    public Double query(String key)
    {

        BasicDBObject specific_key = new BasicDBObject("value",1).append("_id", false);
        DBObject obj = p_z_d_wt_wv.findOne(new    BasicDBObject("key",key),specific_key );    
            return (Double)obj.get("value");
    }

    public void update(boolean ifTrainset, String key, double new_value)
    {
        BasicDBObject query = new BasicDBObject().append("key", key);
        BasicDBObject updated_element = new BasicDBObject();
        updated_element.append("$set", new BasicDBObject().append("value", new_value));
        p_z_d_wt_wv.update(query, updated_element);
    }
}
4

2 に答える 2

0

いくつかの提案

  • データベースのサイズが RAM のサイズを超えている (実際には 2 倍) ためです。おそらく、Shardingを確認する必要があります。Mongo は、データベースのサイズがメモリに収まる場合にうまく機能します。

  • フィールドキーを文字列として保存すると、より多くのメモリが消費されるだけでなく、文字列の比較が遅くなります。このフィールドはNumberLong(MongoDB の Long DataType) に簡単に格納できます。配列の最大サイズが 12*7000*100*500 であることは既にわかっているため

    どのディメンションの最大サイズも 10,000 を超えることはできないと想定しています。その結果、コレクション内の要素の総数は (10000 ** 4) 未満になります。

    したがって、p_z_d_wt_wv 1 [2][3][4] の要素が必要な場合は、インデックスを次のように計算します。

    (10000 ** 0 * 4 ) + (10000 ** 1 * 3 ) + (10000 ** 2 * 3 ) + (10000 * 3 * 1 )

    右から左に移動し、ベースのパワーを増やし、その位置にたまたまある値を掛けて、最終的にそれらの合計を取ります。

    このフィールドにインデックスを付けると、パフォーマンスが向上することが期待できます。

于 2013-07-13T14:14:28.727 に答える
0

大規模な配列があるだけなので、メモリ マップ ファイルを使用することをお勧めします。これは約 32 GB のディスク容量を使用し、はるかに効率的です。それでも、メイン メモリよりも大きなサイズのデータ​​ セットにランダムにアクセスすると、高速な SDD を使用しない限り、常に低速になります (メモリを追加購入した方が安くなります)。

Mongo DB が十分に高速に動作する場合、私は非常に驚かれることでしょう。更新に 10 時間かかる場合は、1 回のスキャンにも 10 時間かかる可能性があります。SSD を使用している場合、メモリ マップ ファイルには約 3 分かかることがあります。データがすべてメモリ内にある場合、たとえば 48 GB (合計ではなく 32 GB 以上の空き容量が必要) がある場合、これは数秒に短縮されます。

ハードウェアの限界に打ち勝つことはできません。;)

于 2013-07-13T14:31:08.500 に答える