2

何千万、何億ものデータをディスクに保存する必要があります。各データには、次のような情報が含まれています。

id=23425
browser=firefox
ip-address=10.1.1.1
outcome=1.0

新しいデータは、1 ミリ秒あたり最大 1 の割合で追加される場合があります。

したがって、キーと値のペアの比較的単純なセットであり、値は文字列、整数、または浮動小数点数にすることができます。場合によっては、フラグ フィールドを 0 から 1 に変更して、特定の ID でデータの一部を更新する必要がある場合があります。ポイント「結果」フィールド - したがって、値のサイズを変更する必要はありません)。

もう 1 つの要件は、このデータをディスクから効率的にストリーミングできる必要があることです (順序は特に重要ではありません)。これは、ハードディスクのヘッドがデータを読み取るためにディスクを飛び回る必要がなく、連続したディスク ブロックで読み取る必要があることを意味します。

私はJavaでこれを書いています。

組み込みデータベースを使用することを考えましたが、DB4O は GPL であり、残りのコードは GPL ではないため、オプションではありません。また、SQL クエリとの間の変換のオーバーヘッドを考えると、組み込み SQL データベースの使用効率についても心配しています。

誰にもアイデアはありますか?これに対するカスタム ソリューションを構築する必要があるのでしょうか (ByteBuffers を直接処理し、ID ルックアップを処理しています)。

4

9 に答える 9

2

H2はどうですか?ライセンスはあなたのために働くはずです。

  • H2は無料で使えます。アプリケーション (商用アプリケーションを含む) に組み込むことができ、配布することができます。
  • あなたのコードのみを含むファイルは、このライセンスの対象外です (これは「商用に適しています」)。
  • H2 ソース コードの変更は公開する必要があります。
  • 何も変更していない場合は、H2 のソース コードを提供する必要はありません。

私は得る

22492 ミリ秒で 1000000 挿入 (44460.252534234394 行/秒)

9565 ミリ秒で 100000 の更新 (10454.783063251438 行/秒)

から

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Random;


/**
 * @author clint
 *
 */
public class H2Test {

  static int testrounds = 1000000;

  public static void main(String[] args) {
    try {
      Class.forName("org.h2.Driver");

    Connection conn = DriverManager.
        getConnection("jdbc:h2:/tmp/test.h2", "sa", "");
    // add application code here
    conn.createStatement().execute("DROP TABLE IF EXISTS TEST");
    conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TEST(id INT PRIMARY KEY, browser VARCHAR(64),ip varchar(16), outcome real)"); 
    //conn.createStatement().execute("CREATE INDEX IDXall ON TEST(id,browser,ip,outcome");


    PreparedStatement ps = conn.prepareStatement("insert into TEST (id, browser, ip, outcome) values (?,?,?,?)");
    long time = System.currentTimeMillis();
    for ( int i = 0; i < testrounds; i++ ) {
      ps.setInt(1,i);
      ps.setString(2,"firefox");
      ps.setString(3,"000.000.000.000");
      ps.setFloat(4,0);
      ps.execute();
    }
    long last = System.currentTimeMillis() ;
    System.out.println( testrounds + " insert in " + (last - time) + "ms (" + ((testrounds)/((last - time)/1000d)) + " row/sec)" );

    ps.close();
    ps = conn.prepareStatement("update TEST set outcome = 1 where id=?");
    Random random = new Random();
    time = System.currentTimeMillis();

    /// randomly updadte 10% of the entries
    for ( int i = 0; i < testrounds/10; i++ ) {
      ps.setInt(1,random.nextInt(testrounds));
      ps.execute();
    }

    last = System.currentTimeMillis();
    System.out.println( (testrounds/10) + " updates in " + (last - time) + "ms (" + ((testrounds/10)/((last - time)/1000d)) + " row/sec)" );

    conn.close();

    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}
于 2009-08-13T22:19:25.197 に答える
1

JDBMは、Java用の優れた組み込みデータベースです(JavaバージョンのBerkleyほどライセンスに煩わされることはありません)。試してみる価値はあります。ACIDの保証が必要ない場合(つまり、クラッシュが発生した場合にデータベースが破損しても問題ない場合)は、トランザクションマネージャーをオフにします(速度が大幅に向上します)。

于 2009-08-14T03:09:47.783 に答える
0

結局、データが入ってくるときにディスクに記録し、更新できるようにメモリに保存することにしました。しばらくして、データをディスクに書き込み、ログを削除します。

于 2009-08-27T18:53:37.717 に答える
0

Oracle の「TimesTen」データベースを調べましたか? 非常に高性能であると思われるインメモリデータベースです。費用やライセンス等はわかりませんが、オラクルのサイトを見て検索してみてください。評価ダウンロードが利用できるはずです。

于 2009-09-02T17:38:52.283 に答える
0

JDK にバンドルされている Apache Derby (または JavaDB) を使用できます。ただし、DBMS が必要な速度を提供しない場合は、特定のファイル構造を自分で実装できます。正確なキー検索だけが必要な場合は、ハッシュ ファイルを使用して実装できます。ハッシュ ファイルは、そのような要件を満たす最速のファイル構造です (DB で使用される B ツリーやグリッドなどの汎用ファイル構造よりもはるかに高速です)。また、許容できるストリーミング効率も提供します。

于 2009-08-14T00:59:37.753 に答える
0

最もアクティブなレコードをメモリにキャッシュし、データの変更を優先度の低い挿入として DB にキューに入れるようなものを書くと、より多くの成功を収めることができると思います。

この方法を使用するとIOがわずかに増加することは理解していますが、数百万のレコードについて話している場合、作成する検索アルゴリズムは本格的なデータベースエンジンよりもはるかに優れているため、それでも高速になると思います.

于 2009-08-13T21:14:43.870 に答える
0

現在 Oracle が所有しているBerkley DBを試すことができます。オープン ソースと商用ライセンスがあります。キー/値モデルを使用します (他の形式のクエリが必要な場合は、インデックスを作成するオプションがあります)。純粋な Java バージョンと、Java バインディングを使用するネイティブ バージョンがあります。

于 2009-08-13T21:17:21.273 に答える
0

http://www.zentus.com/sqlitejdbc/

SQLite データベース (パブリック ドメイン)、BSD ライセンス付きの JDBC コネクタ、多数のプラットフォーム (OSX、Linux、Windows) 向けのネイティブ、残りのエミュレーション。

于 2009-08-13T21:45:42.703 に答える
-1

また、EHCache または JCS に基づいて役立つものがないかどうかも調べます。

于 2009-08-13T22:38:01.737 に答える