Speichern Sie große std :: map, meist auf der Festplatte

7

Ich habe ein C ++ - Programm, das wahrscheinlich eine riesige Menge an Daten generiert - Milliarden von Binärdatensätzen unterschiedlicher Größe, höchstwahrscheinlich weniger als 256 Bytes, aber ein paar Dehnungen bis zu mehreren K. Die meisten Datensätze werden selten sein Sie werden vom Programm nach ihrer Erstellung angeschaut, aber einige werden regelmäßig aufgerufen und geändert. Es gibt keine Möglichkeit zu sagen, welche das sind, wenn sie erstellt werden.

Wenn man die Datenmenge berücksichtigt, gibt es keine Möglichkeit, alles im Speicher zu speichern. Da die Daten jedoch nur nach ihrer Nummer indiziert werden müssen (eine 64-Bit-Ganzzahl), möchte ich nicht den Overhead eines vollwertigen Datenbankprogramms haben. Idealerweise würde ich es gerne als std::map mit seinen auf der Festplatte gespeicherten Daten behandeln, bis sie angefordert werden.

Gibt es eine bereits geschriebene Bibliothek, die das macht, wonach ich suche, oder muss ich sie selbst schreiben?

EDIT: Nach einigem Nachdenken wurde mir klar, dass die Antwort von Rob Walker einen stichhaltigen Punkt hatte: Ich würde mich schwer tun, die gleiche Art von Datenintegrität aus einer Home-Brew-Klasse zu bekommen, die ich bekommen würde eine echte Datenbank.

Obwohl BerkeleyDB (wie von RHM vorgeschlagen) aussieht, als würde es genau das tun, wonach wir suchen, ist die doppelte Lizenzierung ein Kopfzerbrechen, mit dem wir uns nicht befassen wollen. Wenn wir mit dem Code fertig sind und beweisen können, dass er merklich von BerkeleyDB profitieren würde (was er wahrscheinlich tun würde), werden wir das Problem erneut untersuchen.

Ich habe mir Ferruccios Vorschlag von stxxl angeschaut, aber ich konnte nicht sagen, wie es das Programm unterbrechen und neu starten würde (vielleicht mit Änderungen). Mit so vielen Daten würde ich es hassen, einfach zu verwerfen, was es bereits fertiggestellt hat und jedes Mal neu anzufangen, wenn einige der Daten gespeichert werden könnten.

Wir haben also entschieden, zumindest für die anfängliche Entwicklung eine SQLite-Datenbank zu verwenden. Danke an alle, die geantwortet oder gewählt haben.

    
Head Geek 30.12.2008, 01:42
quelle

8 Antworten

5

Ich bezweifle, dass Sie eine Bibliothek finden werden, die genau Ihren Anforderungen entspricht, also müssen Sie entscheiden, welche Features für Sie wirklich wichtig sind und dann entscheiden, ob eine vorhandene DB-Lösung nahe genug ist.

Milliarden von Datensätzen sind in jeder Hinsicht ein großer Datensatz. Mit welcher Rate werden Datensätze generiert? Wie lange bestehen sie? Ändert sich das Zugriffsmuster im Laufe der Zeit?

Werden Aktualisierungen immer mit der gleichen Datenmenge wie das Original durchgeführt?

Ich würde vorschlagen, definitiv zu beweisen, dass eine DB-Lösung nicht funktionieren wird, bevor Sie damit beginnen, Ihre eigenen zu rollen, insbesondere wenn die Integrität der Daten im Vordergrund steht (und normalerweise ...) kann definitiv eine Herausforderung sein. Benötigen Sie eine Transaktionssemantik beim Ändern der Daten? Ist der Client Multithread?

    
Rob Walker 30.12.2008, 01:55
quelle
6

Schauen Sie sich STXXL an.

stxxl::map<> sieht aus, als ob es genau das tut, was Sie brauchen.

    
Ferruccio 30.12.2008 01:59
quelle
4

BerkleyDB könnte gut für dich sein. Es indiziert basierend auf einer Zeichenfolge statt einer Zahl, aber Sie könnten Ihre Zahl als Hex formatieren. Es wird angenommen, dass es bei der datenträgerbasierten Schlüssel / Wert-Suche so schnell wie möglich ist.

    
U62 30.12.2008 01:47
quelle
2

Ich habe Gigabase Ссылка verwendet, in einigen Projekten hat es eine nette C ++ - Schnittstelle, mit der ich gearbeitet habe Millionen von Datensätzen ohne Probleme, unterstützt Rollback. Es hat MIT Lizenz, auch der Autor ist sehr schnell, um Fragen zu beantworten und Bugs zu beheben.

    
Ismael 16.01.2009 02:16
quelle
2

Sie könnten SQLLite verwenden, eine Open-Source-Datenbank, die für die Public Domain freigegeben ist.

Ссылка

Ich zitiere ihre Seite:

  

SQLite ist eine Softwarebibliothek, die eine eigenständige, serverlose Transaktions-SQL-Datenbank-Engine ohne Zerlegung implementiert. SQLite ist die am weitesten verbreitete SQL-Datenbank-Engine der Welt. Der Quellcode für SQLite befindet sich in der öffentlichen Domäne.

Und

  

Die laufende Entwicklung und Wartung von SQLite wird teilweise von Mitgliedern des SQLite-Konsortiums gesponsert, einschließlich: Adobe, Symbian, Bloomberg, Mozilla

Wenn Sie eine leichtgewichtige db brauchen, ist dies vielleicht einfach

    
mellowF 16.01.2009 02:31
quelle
1

Sie werden wahrscheinlich selbst rollen müssen. Ich würde es wahrscheinlich in ein paar MySQL-Tabellen stecken und eine Karte fester Größe (lru) laden. Wenn Sie eine db wirklich vermeiden möchten, platzieren Sie die & lt; 256 oder welche Länge auch immer in festen Datensatz-Direktzugriffsdateien aufgezeichnet werden und die größeren Datensätze als einzelne Dateien speichern.

    
Ray Tayek 30.12.2008 02:08
quelle
0

Abhängig von den Leistungsmerkmalen, die Sie benötigen, ist die Antwort anders. Aber nur die Informationen in der Problembeschreibung gegeben, denke ich, dass eine DB übertrieben ist, und könnte sogar kontraproduktiv sein.

Das Speichern jedes Eintrags als Datei, deren Name der Schlüssel ist (d. h. der Schlüssel "1" entspricht der Datei "1.dat" auf der Platte), unmittelbar nachdem er erzeugt wurde, ist eine einfache Lösung, die mehrere Probleme vermeidet. Angenommen, Sie haben die Kontrolle darüber, auf welchem ​​Dateisystem die Software ausgeführt wird. Wenn Sie ein Dateisystem mit guter Integrität auswählen, sollten Ihre Daten eine gute Integrität aufweisen. Sie könnten viel Code schreiben, um Einträge in einer Datei zu gruppieren und sich dann Gedanken über die Größenanpassung zu machen, oder Sie könnten einfach das Dateisystem das für Sie behandeln lassen (es wurde entwickelt, um mit Dateien umzugehen, deren Größe sich ändert). Sie könnten sich sorgen, sie in einer threadsafe Weise in diese Datei zu schreiben, oder Sie könnten einfach das Dateisystem für Sie behandeln lassen (Dateisysteme sind so konzipiert, dass verschiedene Prozesse gleichzeitig in verschiedene Dateien schreiben). Sie könnten sich Sorgen darüber machen, dass Dateien teilweise auf Festplatte gespeichert werden und Code schreiben, um danach zu suchen, oder Sie können das Dateisystem das für Sie erledigen lassen (Journaling und atomare Schreibvorgänge). Sie könnten sich Gedanken darüber machen, ob Sie die Schreibvorgänge für Änderungen zusammen für die Geschwindigkeit planen, oder Sie können das Dateisystem das für Sie erledigen lassen (Schreib-Caching).

Grundsätzlich sollte ein gutes Dateisystem und Betriebssystem das alles für Sie übernehmen, und das Hinzufügen einer Datenbank darüber, die versucht, all diese Funktionen zu duplizieren, erzeugt nur mehr Komplexität und mehr Möglichkeiten für Fehler. Wenn Sie die Daten nach verschiedenen Feldern indizieren müssen, kann eine Datenbank sinnvoll sein, aber in Ihrer Beschreibung haben Sie gesagt, dass Sie die Daten nur jedes Mal mit dem gleichen Integer-Schlüssel indexieren müssen.

    
Joseph Garvin 31.12.2008 16:57
quelle
0

Ich stimme anderen zu, dass BerkeleyDB, sqlite oder gigabase gute Lösungen sein sollten.

Aber Ihre eigene Lösung zu schreiben sollte auch nicht zu schwer sein.

Ich habe eine einfache Lösung, aber es gibt drei Voraussetzungen:

  1. Sie können zumindest std::vector<int64> mit numkey Elementen im Speicher behalten.
  2. Ihre Schlüssel sind oder können kontinuierlich gemacht werden.
  3. Nachdem die Datei geschrieben wurde, hat jede Datensatzgröße eine feste maxsize , d. h. ihre Größe kann nicht erhöht werden.

Wenn diese Voraussetzungen erfüllt sind, besteht die einfache Lösung darin, die Dateiposition (int64) jedes Schlüssels (int64) in dem Vektor im Speicher zu speichern. Suchen Sie für die Suche einfach die Dateiposition aus dem Vektor seek an diese Position, wobei Sie die Datensatzgröße als ersten Eintrag finden, und lesen Sie size bytes.

    
Frank 06.02.2010 02:43
quelle

Tags und Links