Ich habe einen Datensatz von 1-Minuten-Daten von 1000 Aktien seit 1998, die sich insgesamt um (2012-1998)*(365*24*60)*1000 = 7.3 Billion
Zeilen drehen.
Die meisten (99,9%) der Zeit werde ich nur durchführen Leseanforderungen.
Was ist der beste Weg, um diese Daten in einer Datenbank zu speichern?
- 1 großer Tisch mit 7,3B Zeilen?
- 1000 Tabellen (eine für jedes Aktiensymbol) mit jeweils 7,3 Millionen Zeilen?
- eine Empfehlung der Datenbank-Engine? (Ich plane, MySQL von Amazon RDS zu verwenden.)
Ich bin es nicht gewohnt, mit so großen Datensätzen umzugehen, daher ist dies eine hervorragende Gelegenheit für mich, etwas zu lernen. Ich werde Ihre Hilfe und Ihren Rat sehr schätzen.
Bearbeiten:
Dies ist eine Beispielzeile:
'XX', 20041208, 938, 43.7444, 43.7541, 43.735, 43.7444, 35116.7, 1, 0, 0
Spalte 1 ist das Aktiensymbol, Spalte 2 ist das Datum, Spalte 3 ist die Minute, der Rest sind Open-High-Low-Close-Preise, Volumen und 3 ganzzahlige Spalten.
Die meisten Fragen lauten wie folgt: "Geben Sie mir die Preise für AAPL zwischen dem 12. April 2012, 12:15 Uhr und dem 13. April 2012, 12:52 Uhr."
Über die Hardware: Ich plane, Amazon RDS zu verwenden, damit ich flexibel bin
Antworten:
Erzählen Sie uns von den Abfragen und Ihrer Hardwareumgebung.
Ich wäre sehr, sehr versucht, NoSQL mit Hadoop oder ähnlichem zu verwenden, solange Sie die Parallelität nutzen können.
Aktualisieren
OK warum?
Beachten Sie zunächst, dass ich nach den Fragen gefragt habe. Sie können - und wir können es sicherlich nicht - diese Fragen beantworten, ohne zu wissen, wie die Arbeitsbelastung ist. (Ich werde übrigens bald einen Artikel darüber veröffentlichen, aber ich kann ihn heute nicht verlinken.) Aber das Ausmaß des Problems lässt mich darüber nachdenken, von einer großen alten Datenbank wegzugehen, weil
Meine Erfahrung mit ähnlichen Systemen legt nahe, dass der Zugriff entweder groß sequentiell (Berechnung einer Art Zeitreihenanalyse) oder sehr sehr flexibel im Data Mining (OLAP) erfolgt. Sequentielle Daten können sequentiell besser und schneller verarbeitet werden. OLAP bedeutet, viele, viele Indizes zu berechnen, was entweder viel Zeit oder viel Platz in Anspruch nimmt.
Wenn Sie jedoch in einer OLAP-Welt effektiv große Datenmengen ausführen, ist ein spaltenorientierter Ansatz möglicherweise am besten.
Wenn Sie zufällige Abfragen durchführen möchten, insbesondere Kreuzvergleiche durchführen möchten, ist ein Hadoop-System möglicherweise effektiv. Warum? weil
Tatsache ist jedoch, dass es unmöglich ist, etwas Bestimmtes zu sagen, bis wir über Ihre Arbeitsbelastung Bescheid wissen.
quelle
Datenbanken sind also für Situationen gedacht, in denen Sie ein großes, kompliziertes Schema haben, das sich ständig ändert. Sie haben nur eine "Tabelle" mit einer Hand voll einfacher numerischer Felder. Ich würde es so machen:
Bereiten Sie eine C / C ++ - Struktur für das Datensatzformat vor:
Berechnen Sie dann sizeof (StockPrice [N]), wobei N die Anzahl der Datensätze ist. (Auf einem 64-Bit-System) Es sollte nur ein paar hundert Gig sein und auf eine 50-Dollar-Festplatte passen.
Dann kürzen Sie eine Datei auf diese Größe und mmap (unter Linux oder verwenden Sie CreateFileMapping unter Windows) in den Speicher:
Setzen Sie den mmaped-Zeiger auf StockPrice * und übergeben Sie Ihre Daten, indem Sie das Array ausfüllen. Schließen Sie die mmap, und jetzt haben Sie Ihre Daten in einem großen binären Array in einer Datei, die später erneut mmaped werden kann.
Sie können es jetzt wieder schreibgeschützt von jedem Programm aus zuordnen und Ihre Daten sind sofort verfügbar:
Jetzt können Sie es wie ein In-Memory-Array von Strukturen behandeln. Sie können verschiedene Arten von Indexdatenstrukturen erstellen, je nachdem, was Ihre "Abfragen" sind. Der Kernel wird die Daten transparent auf / von der Festplatte austauschen, so dass sie wahnsinnig schnell sind.
Wenn Sie ein bestimmtes Zugriffsmuster erwarten (z. B. ein zusammenhängendes Datum), sortieren Sie das Array am besten in dieser Reihenfolge, damit es nacheinander auf die Festplatte gelangt.
quelle
Das einmalige Speichern und mehrmalige Lesen zeitbasierter numerischer Daten ist ein Anwendungsfall, der als "Zeitreihe" bezeichnet wird. Andere gängige Zeitreihen sind Sensordaten im Internet der Dinge, Serverüberwachungsstatistiken, Anwendungsereignisse usw.
Diese Frage wurde 2012 gestellt. Seitdem haben mehrere Datenbank-Engines Funktionen speziell für die Verwaltung von Zeitreihen entwickelt. Ich habe großartige Ergebnisse mit der InfluxDB erzielt , die Open Source ist, in Go geschrieben und MIT-lizenziert ist.
InfluxDB wurde speziell zum Speichern und Abfragen von Zeitreihendaten optimiert. Viel mehr als Cassandra , die oft als großartig für die Speicherung von Zeitreihen angepriesen wird:
Die Optimierung für Zeitreihen war mit bestimmten Kompromissen verbunden. Beispielsweise:
In Open Source Benchmarks ,
Abfragen sind auch sehr einfach. Wenn Ihre Zeilen so aussehen
<symbol, timestamp, open, high, low, close, volume>
, können Sie mit InfluxDB genau das speichern und dann einfach abfragen. Sagen wir für die letzten 10 Minuten der Daten:Es gibt keine IDs, keine Schlüssel und keine Verknüpfungen. Sie können viele interessante Aggregationen durchführen . Sie müssen die Tabelle nicht wie bei PostgreSQL vertikal partitionieren oder Ihr Schema wie bei MongoDB in Sekundenarrays verzerren . Außerdem komprimiert InfluxDB sehr gut, während PostgreSQL keine Komprimierung für den Datentyp durchführen kann, über den Sie verfügen .
quelle
Okay, das ist etwas anders als bei den anderen Antworten, aber ... es fühlt sich für mich so an, als ob Sie die Daten in einem Dateisystem (vielleicht ein Bestand pro Datei) mit einer festen Datensatzgröße haben und an die Daten gelangen können ganz einfach: Wenn Sie eine Abfrage für einen bestimmten Bestand und einen bestimmten Zeitraum haben, können Sie an der richtigen Stelle suchen, alle benötigten Daten abrufen (Sie wissen genau, wie viele Bytes Sie haben) und die Daten in das gewünschte Format umwandeln (was möglich ist) Seien Sie sehr schnell, abhängig von Ihrem Speicherformat) und Sie sind weg.
Ich weiß nichts über Amazon-Speicher, aber wenn Sie keinen direkten Dateizugriff haben, könnten Sie grundsätzlich Blobs haben - Sie müssten große Blobs ausgleichen (weniger Datensätze, aber wahrscheinlich mehr Daten lesen, als Sie jeweils benötigen Zeit) mit kleinen Blobs (mehr Datensätze, die mehr Overhead verursachen und wahrscheinlich mehr Anfragen, um sie zu erreichen, aber jedes Mal weniger nutzlose Daten).
Als nächstes fügen Sie Caching hinzu - ich würde beispielsweise vorschlagen, verschiedenen Servern unterschiedliche Bestände zuzuweisen - und Sie können so ziemlich nur aus dem Speicher dienen. Wenn Sie sich genügend Speicher auf genügend Servern leisten können, umgehen Sie den Teil "Load on Demand" und laden Sie einfach alle Dateien beim Start. Dies würde die Dinge auf Kosten eines langsameren Starts vereinfachen (was sich offensichtlich auf das Failover auswirkt, es sei denn, Sie können es sich leisten, immer zwei Server für einen bestimmten Bestand zu haben, was hilfreich wäre).
Beachten Sie, dass Sie das Aktiensymbol, das Datum oder die Minute nicht für jeden Datensatz speichern müssen, da diese in der zu ladenden Datei und der Position in der Datei enthalten sind. Sie sollten auch überlegen, welche Genauigkeit Sie für jeden Wert benötigen und wie Sie diese effizient speichern können. Sie haben in Ihrer Frage 6SF angegeben, die Sie in 20 Bit speichern können. Speichern Sie möglicherweise drei 20-Bit-Ganzzahlen in 64-Bit-Speicher: Lesen Sie sie als
long
(oder wie auch immer Ihr 64-Bit-Ganzzahlwert lautet ) und verwenden Sie Maskierung / Verschiebung, um sie auf drei Ganzzahlen zurückzusetzen. Sie müssen natürlich wissen, welche Skalierung Sie verwenden sollen - die Sie wahrscheinlich in die freien 4 Bits codieren könnten, wenn Sie sie nicht konstant machen können.Sie haben nicht gesagt, wie die anderen drei Ganzzahlspalten aussehen, aber wenn Sie auch für diese drei mit 64 Bit davonkommen könnten, könnten Sie einen ganzen Datensatz in 16 Bytes speichern. Das sind nur ~ 110 GB für die gesamte Datenbank, was nicht wirklich viel ist ...
EDIT: Die andere zu berücksichtigende Sache ist, dass sich die Aktie vermutlich am Wochenende - oder sogar über Nacht - nicht ändert. Wenn die Börse nur 8 Stunden pro Tag, 5 Tage pro Woche geöffnet ist, benötigen Sie nur 40 Werte pro Woche anstelle von 168. Zu diesem Zeitpunkt könnten Sie nur noch etwa 28 GB Daten in Ihren Dateien haben ... was sich anhört viel kleiner als Sie wahrscheinlich ursprünglich gedacht hatten. Es ist sehr vernünftig , so viele Daten im Speicher zu haben .
EDIT: Ich denke, ich habe die Erklärung verpasst, warum dieser Ansatz hier gut passt: Sie haben einen sehr vorhersehbaren Aspekt für einen großen Teil Ihrer Daten - den Börsenticker, das Datum und die Uhrzeit. Indem Sie den Ticker einmal (als Dateinamen) ausdrücken und das Datum / die Uhrzeit vollständig in der Position der Daten implizieren , entfernen Sie eine ganze Reihe von Arbeiten. Es ist ein bisschen wie der Unterschied zwischen a
String[]
und aMap<Integer, String>
- zu wissen, dass Ihr Array-Index immer bei 0 beginnt und in Schritten von 1 bis zur Länge des Arrays ansteigt, ermöglicht einen schnellen Zugriff und eine effizientere Speicherung.quelle
Nach meinem Verständnis wurde HDF5 speziell für die Zeitreihenspeicherung von Bestandsdaten als eine mögliche Anwendung entwickelt. Mitstapler haben gezeigt, dass HDF5 für große Datenmengen geeignet ist: Chromosomen , Physik .
quelle
Hier ist ein Versuch, einen Market Data Server über der Microsoft SQL Server 2012-Datenbank zu erstellen, der für die OLAP-Analyse, ein kostenloses Open Source-Projekt, geeignet sein sollte:
http://github.com/kriasoft/market-data
quelle
Erstens gibt es nicht 365 Handelstage im Jahr, mit Feiertagen 52 Wochenenden (104) = sagen wir 250 x die tatsächlichen Stunden des Tagesmarkt ist geöffnet, wie jemand sagte, und das Symbol als Primärschlüssel zu verwenden, ist keine gute Idee Da sich Symbole ändern, verwenden Sie eine k_equity_id (numerisch) mit einem Symbol (char), da Symbole wie A oder GAC-DB-B.TO sein können. In Ihren Datentabellen mit Preisinformationen haben Sie also Ihre Schätzung von 7,3 Milliarden sind weit überkalkuliert, da es 14 Jahre lang nur etwa 1,7 Millionen Zeilen pro Symbol sind.
k_equity_id k_date k_minute
und für die EOD-Tabelle (die 1000x über den anderen Daten angezeigt wird)
k_equity_id k_date
Zweitens: Speichern Sie Ihre OHLC-Daten nicht nach Minuten in derselben DB-Tabelle wie und in der EOD-Tabelle (Tagesende), da jeder, der über einen Zeitraum von einem Jahr einen pnf oder ein Liniendiagramm anzeigen möchte, kein Interesse an by hat die winzigen Informationen.
quelle
Lassen Sie mich empfehlen, dass Sie sich Apache Solr ansehen , das meiner Meinung nach ideal für Ihr spezielles Problem ist. Grundsätzlich würden Sie zuerst Ihre Daten indizieren (jede Zeile ist ein "Dokument"). Solr ist für die Suche optimiert und unterstützt von Haus aus Bereichsabfragen zu Datumsangaben. Ihre nominelle Anfrage,
"Give me the prices of AAPL between April 12 2012 12:15 and April 13 2012 12:52"
würde zu etwas übersetzen wie:
Angenommen, "stock" ist der Aktienname und "date" ist ein "DateField", das aus den Spalten "date" und "minute" Ihrer Eingabedaten für die Indizierung erstellt wurde. Solr ist unglaublich flexibel und ich kann wirklich nicht genug gute Dinge darüber sagen. Wenn Sie beispielsweise die Felder in den Originaldaten pflegen müssen, können Sie wahrscheinlich eine Möglichkeit finden, das "DateField" als Teil der Abfrage (oder des Filters) dynamisch zu erstellen.
quelle
Ich denke, jedes größere RDBMS würde damit umgehen. Auf atomarer Ebene erscheint eine Tabelle mit einer korrekten Partitionierung sinnvoll (Partition basierend auf Ihrer Datennutzung, falls festgelegt - dies ist wahrscheinlich entweder ein Symbol oder ein Datum).
Sie können auch aggregierte Tabellen erstellen, um einen schnelleren Zugriff über der atomaren Ebene zu erhalten. Wenn sich Ihre Daten beispielsweise am Tag befinden, Sie jedoch häufig Daten auf Wochen- oder sogar Monatsebene zurückerhalten, kann dies in einer aggregierten Tabelle vorberechnet werden. In einigen Datenbanken kann dies über eine zwischengespeicherte Ansicht erfolgen (verschiedene Namen für verschiedene DB-Lösungen - im Grunde genommen jedoch eine Ansicht der Atomdaten, aber sobald sie ausgeführt wird, wird die Ansicht in einer festen temporären Tabelle zwischengespeichert / gehärtet), die nach nachfolgenden übereinstimmenden Abfragen abgefragt wird Dies kann in regelmäßigen Abständen gelöscht werden, um Speicherplatz freizugeben.
Ich denke, wir könnten Ihnen mit einer Vorstellung von der Datennutzung mehr helfen.
quelle
Sie sollten die langsamen Lösungen mit einem einfachen, im Speicher optimierten Modell vergleichen. Unkomprimiert passt es in einen 256 GB RAM-Server. Ein Schnappschuss passt in 32 K und Sie indizieren ihn einfach nach Datum / Uhrzeit und Bestand. Dann können Sie spezielle Schnappschüsse erstellen, da das Öffnen eines Schnappschusses oft dem Schließen des vorherigen entspricht.
[Bearbeiten] Warum ist es Ihrer Meinung nach sinnvoll, überhaupt eine Datenbank (rdbms oder nosql) zu verwenden? Diese Daten ändern sich nicht und passen in den Speicher. Dies ist kein Anwendungsfall, in dem eine Datenbank einen Mehrwert bieten kann.
quelle
Wenn Sie die Hardware haben, empfehle ich MySQL Cluster . Sie erhalten die MySQL / RDBMS-Schnittstelle, mit der Sie so vertraut sind, und Sie erhalten schnelle und parallele Schreibvorgänge. Lesevorgänge sind aufgrund der Netzwerklatenz langsamer als normales MySQL. Sie haben jedoch den Vorteil, dass Sie Abfragen und Lesevorgänge aufgrund der Funktionsweise von MySQL Cluster und der NDB-Speicher-Engine parallelisieren können.
Stellen Sie jedoch sicher, dass Sie über genügend MySQL Cluster-Computer und genügend Speicher / RAM für jeden dieser Computer verfügen. MySQL Cluster ist eine stark speicherorientierte Datenbankarchitektur.
Oder Redis , wenn Ihnen eine Schlüsselwert- / NoSQL-Schnittstelle für Ihre Lese- / Schreibvorgänge nichts ausmacht. Stellen Sie sicher, dass Redis über genügend Speicher verfügt - es ist superschnell für Lese- und Schreibvorgänge. Sie können damit grundlegende Abfragen durchführen (allerdings kein RDBMS), ist aber auch eine speicherinterne Datenbank.
Wie andere gesagt haben, hilft es, mehr über die Abfragen zu wissen, die Sie ausführen werden.
quelle
Sie möchten, dass die Daten in einer Spaltentabelle / Datenbank gespeichert werden . Datenbanksysteme wie Vertica und Greenplum sind Spaltendatenbanken, und ich glaube, SQL Server ermöglicht jetzt Spaltentabellen. Diese sind äußerst effizient für die
SELECT
Bearbeitung sehr großer Datenmengen. Sie können auch große Datenmengen effizient importieren.Eine freie Säulendatenbank ist MonetDB .
quelle
Wenn Ihr Anwendungsfall darin besteht, Zeilen ohne Aggregation einfach zu lesen, können Sie Aerospike-Cluster verwenden. Es befindet sich in der Speicherdatenbank mit Unterstützung des Dateisystems für die Persistenz. Es ist auch SSD-optimiert.
Wenn Ihr Anwendungsfall aggregierte Daten benötigt, wählen Sie den Mongo DB-Cluster mit Datumsbereich-Sharding. Sie können Schraubstockdaten in Shards zusammenfassen.
quelle