Comment puis-je conserver des données sur le disque, et à la fois mettre à jour au hasard, et le diffuser efficacement de retour dans la RAM?

StackOverflow https://stackoverflow.com/questions/1274562

Question

Je dois stocker jusqu'à des dizaines, voire des centaines de millions de morceaux de données sur le disque. Chaque morceau de données contient des informations telles que:

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

De nouvelles pièces de données peuvent être ajoutées au taux de mise à 1 par milliseconde.

est un ensemble relativement simple de paires clé-valeur, où les valeurs peuvent être des chaînes, des entiers ou des flotteurs. Je peux parfois besoin de mettre à jour la donnée avec un identifiant particulier, en changeant le champ de drapeau de 0 à 1. En d'autres termes, je dois être capable de faire des recherches clés aléatoires par identifiant et modifier les données (en fait seulement le flottant champ Point « de résultat » - donc je ne serai jamais besoin de modifier la taille de la valeur)

.

L'autre exigence est que je dois être en mesure de diffuser ces données hors disque (l'ordre est pas particulièrement important) efficace. Cela signifie que la tête de disque dur ne devrait pas avoir besoin de sauter autour du disque pour lire les données, il devrait plutôt être lu dans des blocs de disque consécutifs.

J'écris ceci en Java.

J'ai pensé à l'aide d'une base de données intégrée, mais db4o est pas une option car il est GPL et le reste de mon code n'est pas. Je me inquiète aussi l'efficacité de l'utilisation d'une base de données SQL intégrée, étant donné les frais généraux de la traduction vers et à partir des requêtes SQL.

Quelqu'un at-il des idées? Puis-je construire une solution personnalisée à ce (où je traite directement avec ByteBuffers et manipulation de l'identifiant recherche)?

Était-ce utile?

La solution 7

A la fin j'ai décidé d'enregistrer les données sur le disque comme il arrive, et aussi garder en mémoire où je peux le mettre à jour. Après une période de temps, j'écrire les données sur le disque et supprimer le journal.

Autres conseils

Que diriez-vous H2 ? Licence devrait travailler pour vous.

  • Vous pouvez utiliser H2 gratuitement. Vous pouvez l'intégrer dans votre application (Y compris les applications commerciales), et vous pouvez le distribuer.
  • Fichiers ne contenant que votre code ne sont pas couvert par cette licence (il est 'Amical commercial').
  • Modifications au code source H2 doit être publié.
  • Vous n'avez pas besoin de fournir le code source de H2 si vous ne l'avez pas rien modifier.

Je reçois

1000000 insert en 22492ms (44460,252534234394 rangée / sec)

100000 mises à jour dans 9565ms (10454,783063251438 rangée / sec)

de

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();
    }
  }

}

JDBM est une grande base de données intégrée pour Java (et non encombrées de licence que la version Java de Berkley). Il serait intéressant d'essayer. Si vous n'avez pas besoin de garanties ACID (à savoir que vous êtes OK avec la base de données d'obtenir endommagé en cas d'accident), désactivez le gestionnaire de transactions (augmente considérablement la vitesse).

Je pense que vous auriez beaucoup plus de succès à écrire quelque chose qui met en cache les plus actifs dans les enregistrements de données de la mémoire et les files d'attente des changements comme un insert de faible priorité dans le DB.

Je crois savoir qu'il ya une légère augmentation de IO en utilisant cette méthode, mais si vous parlez des millions de disques, je pense que ce serait encore plus rapide car tout algorithme de recherche que vous créez va être concurrencés grandement par aa moteur de base de données à part entière.

Vous pouvez essayer Berkley DB qui appartient maintenant à Oracle . Ils ont Open Source et des licences commerciales. Il utilise un modèle clé / valeur (avec une option pour créer des index si d'autres formes de requêtes sont nécessaires). Il existe une version pure Java et une version native avec des liaisons Java.

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

base de données SQLite (domaine public), connecteur JDBC avec licence BSD, natif pour un tas de plates-formes (Mac OS X, Linux, Windows), émulation pour le reste.

Vous pouvez utiliser Apache Derby (ou JavaDB) qui est livré avec JDK. Toutefois, si un SGBD ne fournit pas la vitesse nécessaire, vous pouvez mettre en œuvre une structure de fichier spécifique vous-même. Si seulement la recherche de clé exacte est nécessaire, vous pouvez utiliser un hachage fichier pour la mettre en œuvre. Le hachage fichier est la structure de fichier le plus rapide de ces exigences (beaucoup plus rapide que les structures de fichiers usage général comme B-arbres et grilles qui sont utilisés dans BDs). Il fournit également l'efficacité de diffusion en continu acceptable.

Avez-vous pris un coup d'œil à la base de données « TimesTen » Oracle? Son une en mémoire db qui est censé être très haute performance. Je ne sais pas sur les coûts / licences, etc, mais jetez un oeil sur le site Oracles et rechercher. télécharger Eval devrait être disponible.

Je voudrais aussi jeter un coup d'oeil pour voir s'il y a quelque chose existant basé soit sur EHCache ou JCS qui pourrait aider.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top