MessagePack ist ein von Herrn Furuhashi von Treasure Data vorgeschlagenes und implementiertes Datenserialisierungsformat, das als Format für die Kommunikation zwischen fluentd bekannt ist. Und ich denke du bist. Persönlich verwende ich dies häufig, um Daten bei der Datenanalyse zu speichern, und in diesem Artikel wird die Methode vorgestellt.
Obwohl ich versuche, den Artikel so genau wie möglich zu schreiben, bin ich relativ amateurhaft in Bezug auf Datenanalyse, daher begrüße ich Ihre Vorschläge und Kommentare.
Sie möchten lediglich die ** Daten, die für die Analyse im MessagePack-Format erhalten wurden, in einer Datei speichern und die Daten zum Zeitpunkt der Analyse lesen **.
Normalerweise scheint es bei der Durchführung von Datenanalysen usw. der königliche Weg zu sein, diese einmal in einer Datenbank usw. zu speichern und dann die Analyse durchzuführen. In den folgenden Fällen denke ich jedoch, dass das Speichern und Lesen im MessagePack-Format von Vorteil ist. ..
Wenn die von einem bestimmten System ausgegebenen Daten beispielsweise JSON im Wörterbuchformat sind, sind die in jedem Datensatz enthaltenen Schlüssel unterschiedlich, das Format der als Wert eingegebenen Daten ist unterschiedlich und es ist nicht bekannt, ob das Wörterbuchformat oder das Arrayformat vorliegt. Oder sowas ähnliches. Selbst wenn sich der Schlüssel oder Wert ändert, ist es gut, wenn ein solches Schema oder eine solche Spezifikation richtig definiert ist. Es gibt jedoch Fälle, in denen keine andere Wahl bleibt, als aus den tatsächlichen Daten ohne die Spezifikation zu schätzen.
In einem solchen Fall kann MessagePack die hierarchische Struktur wie Wörterbücher und Arrays fast so konvertieren und verwenden, dass es einfach ist, sie in die Datei einzufügen, ohne vorerst über irgendetwas nachzudenken. Beim Abrufen von Daten für die Datenanalyse wird die Daten-E / A häufig zu einem Engpass. Wenn Sie sie also lokal in einem Dateiformat speichern, können Sie später leichter Versuche und Fehler durchführen.
Es gibt viele Dinge, die als Datenanalyse bezeichnet werden können, aber es ist häufig erforderlich, eine "explorative Datenanalyse" durchzuführen, um das gesamte Bild zu erfassen und eine Hypothese zu formulieren, während die Daten in dem Stadium geknetet werden, in dem keine ausreichende Hypothese aufgestellt werden kann. In einem solchen Fall können Sie die Daten in ein einfach zu verarbeitendes Format konvertieren, nur die erforderlichen Daten extrahieren und speichern und so weiter. In diesem Fall kann es zu Problemen mit dem Datenformat kommen, z. B. "Ich möchte dieses Attribut für einen Moment hinzufügen" oder "Es scheint besser, es als Wörterbuch anstelle einer Liste zu speichern".
Bei der Verarbeitung, während das Datenformat auf diese Weise flexibel geändert wird, wenn die Codeseite geändert wird, indem das Schema erneut an einer anderen Stelle als dem Code definiert wird, der die Daten verarbeitet (z. B. Erstellen einer Tabelle mit SQL) usw. In jedem Fall können Inkonsistenzen auftreten, die sehr ärgerlich sein können. Wenn Sie Daten im MessagePack-Format speichern möchten, müssen Sie natürlich das Datenformat sowohl zum Schreiben als auch zum Lesen anpassen, aber der Arbeitsaufwand ist minimal.
(Wenn Sie jedoch bis zu einem gewissen Grad keine Kommentare hinterlassen, verstehen Sie die Bedeutung möglicherweise überhaupt nicht, selbst wenn Sie den Code einige Monate später selbst überprüfen ...)
DB als Middleware speichert nicht nur Daten, sondern bietet auch verschiedene Funktionen wie das Einstellen von Schlüsseln und die Gewährleistung der Zuverlässigkeit. Dies erfordert mehr Aufwand als das einfache Schreiben auf die Festplatte. .. Dies kann durch Techniken wie die Lastverteilung gelöst werden. Wenn Sie jedoch nur "ein wenig Daten speichern" möchten, können Sie diese in das MessagePack-Format konvertieren und direkt als Datei schreiben. Die Leistung beim Schreiben und Lesen von Dateien wird jedoch fast unverändert angewendet.
Die Zuverlässigkeit entspricht jedoch dem Schreiben in eine Datei, und es wird davon ausgegangen, dass beim Lesen alle Daten gelesen werden.
Andererseits gibt es natürlich Fälle, in denen es nicht geeignet ist, im MessagePack-Format zu speichern und die Daten zu analysieren.
Die folgenden Technologien können als Alternativen betrachtet werden. Bitte wählen Sie je nach Situation.
Es ist besser, CSV (oder TSV) zu verwenden, wenn die Daten in einem Spaltenformat mit nahezu fester Länge und nicht hierarchisch strukturiert sind. Es ist jedoch einfacher, MessagePack zu verwenden, wenn Elemente variabler Länge und hierarchische Strukturen enthalten sind.
Sie können in eine dokumentorientierte Datenbank einfügen, ohne ein Schema zu definieren, sodass Sie dies auch vor dem Speichern von Daten tun können. Die Leistung des Einfügens scheint jedoch [3.500 Einfügen / Sek. Zu viel] zu sein (https://www.arangodb.com/2015/10/benchmark-postgresql-mongodb-arangodb/), und beim Schreiben mit MessagePack wird nur direkt auf die Festplatte geschrieben Das Speichern mit MessagePack, das die Leistung der Festplatten-E / A beibehält, ist überwältigend schneller. Wenn Sie jedoch später Schlüssel erstellen möchten, ist MongoDB besser geeignet.
Es ist im Vergleich zu MessagePack hinsichtlich Verarbeitungsgeschwindigkeit und Datengröße nachteilig (Referenz). Außerdem ist JSON ein Modul, das in Schritten wie ijson ausgelesen wird, wenn Sie mehrere Objekte in ein Datensegment (z. B. eine Datei) einfügen möchten. Wenn Sie es nicht verwenden, müssen Sie alles auf einmal analysieren. Wenn also die Anzahl der Daten groß ist, ist die Verarbeitung auf einem schlechten Computer schwierig. Wenn Sie es jedoch wie ijson schreiben, wird der Code kompliziert, sodass ich persönlich denke, dass es einfacher ist, Daten kontinuierlich in einem Datensegment zu speichern und gehorsam abzurufen.
Protokollpuffer sind als eine der Serialisierungstechnologien bekannt, aber es braucht Zeit, um Daten zu verarbeiten, deren Schema unklar ist, da das Schema auf der Seite des Verarbeitungscodes definiert werden muss. Als Datenserialisierung als Schnittstelle zwischen Software betrachtet, ist dies praktisch, da es das Schema reguliert. In Fällen, in denen Sie nicht wissen, welche Art von Schemadaten kommen werden, wird es jedoch schwierig, damit umzugehen.
Auf der offiziellen Seite gibt es viele Erklärungen, daher muss ich nicht viel reden, aber ich werde mich darauf konzentrieren, in die Datei zu schreiben und zu lesen und den Beispielcode einzuführen. Der Code ist auch auf [github] zu finden (https://github.com/m-mizutani/msgpack-file-sample).
In jedem Fall müssen die folgenden Daten in die Datei "data.msg" geschrieben / gelesen werden.
{
"name": "Alice",
"age": 27,
"hist": [5, 3, 1]
}
{
"name": "Bob",
"age": 33,
"hist": [4, 5]
}
Paket msgpack-python
ist erforderlich.
Installation
$ pip install msgpack-python
Schreiben Sie einen Beispielcode
# coding: UTF-8
import msgpack
obj1 = {
"name": "Alice",
"age": 27,
"hist": [5, 3, 1]
}
obj2 = {
"name": "Bob",
"age": 33,
"hist": [4, 5]
}
with open('data.msg', 'w') as fd:
fd.write(msgpack.packb(obj1))
fd.write(msgpack.packb(obj2))
Lesen Sie den Beispielcode
# coding: UTF-8
import msgpack
for msg in msgpack.Unpacker(open('data.msg', 'rb')):
print msg
Paket msgpack
ist erforderlich.
$ gem install msgpack
Schreiben Sie einen Beispielcode
# -*- coding: utf-8 -*-
require "msgpack"
obj1 = {
"name": "Alice",
"age": 27,
"hist": [5, 3, 1]
}
obj2 = {
"name": "Bob",
"age": 33,
"hist": [4, 5]
}
File.open("data.msg", "w") do |file|
file.write(obj1.to_msgpack)
file.write(obj2.to_msgpack)
end
Lesen Sie den Beispielcode
# -*- coding: utf-8 -*-
require "msgpack"
File.open("data.msg") do |file|
MessagePack::Unpacker.new(file).each do |obj|
puts obj
end
end
Es gibt einige wichtige MessagePack-Bibliotheken, aber dieses Mal werde ich "msgpack-lite" für den Code verwenden.
$ npm install msgpack-lite
Schreiben Sie einen Beispielcode
const fs = require('fs');
const msgpack = require('msgpack-lite');
const obj1 = {
name: "Alice",
age: 27,
hist: [5, 3, 1]
};
const obj2 = {
name: "Bob",
age: 33,
hist: [4, 5]
};
fs.open('data.msg', 'w', (err, fd) => {
fs.writeSync(fd, msgpack.encode(obj1));
fs.writeSync(fd, msgpack.encode(obj2));
});
Lesen Sie den Beispielcode
const fs = require('fs');
const msgpack = require('msgpack-lite');
var rs = fs.createReadStream('data.msg');
var ds = msgpack.createDecodeStream();
rs.pipe(ds).on('data', (msg) => {
console.log(msg);
});
Die msgpackc
Bibliothek ist erforderlich. Für MacOS können Sie es mit Brew installieren.
$ brew install msgpack
Schreiben Sie einen Beispielcode
#include <msgpack.hpp>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fd = open("data.msg", O_WRONLY | O_CREAT, 0600);
msgpack::sbuffer buf1, buf2;;
msgpack::packer<msgpack::sbuffer> pk1(&buf1), pk2(&buf2);
pk1.pack_map(3);
pk1.pack("name"); pk1.pack("Alice");
pk1.pack("age"); pk1.pack(27);
pk1.pack("hist");
pk1.pack_array(3);
pk1.pack(5); pk1.pack(3); pk1.pack(1);
write(fd, buf1.data(), buf1.size());
pk2.pack_map(3);
pk2.pack("name"); pk2.pack("Bob");
pk2.pack("age"); pk2.pack(33);
pk2.pack("hist");
pk2.pack_array(2);
pk2.pack(4); pk2.pack(5);
write(fd, buf2.data(), buf2.size());
close(fd);
return 0;
}
Lesen Sie den Beispielcode
#include <msgpack.hpp>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
static const size_t BUFSIZE = 4; //Wagen Sie es, die Puffergröße zu verkleinern
int rc;
char buf[BUFSIZE];
int fd = open("data.msg", O_RDONLY);
msgpack::unpacker unpkr;
while (0 < (rc = read(fd, buf, sizeof(buf)))) {
unpkr.reserve_buffer(rc);
memcpy(unpkr.buffer(), buf, rc);
unpkr.buffer_consumed(rc);
msgpack::object_handle result;
while (unpkr.next(result)) {
const msgpack::object &obj = result.get();
if (obj.type == msgpack::type::MAP) {
printf("{\n");
msgpack::object_kv* p(obj.via.map.ptr);
for(msgpack::object_kv* const pend(obj.via.map.ptr + obj.via.map.size);
p < pend; ++p) {
std::string key;
p->key.convert(key);
if (key == "name") {
std::string value;
p->val.convert(value);
printf(" %s: %s,\n", key.c_str(), value.c_str());
}
if (key == "age") {
int value;
p->val.convert(value);
printf(" %s: %d,\n", key.c_str(), value);
}
if (key == "hist") {
msgpack::object arr = p->val;
printf (" %s, [", key.c_str());
for (int i = 0; i < arr.via.array.size; i++) {
int value;
arr.via.array.ptr[i].convert(value);
printf("%d, ", value);
}
printf ("],\n");
}
}
printf("}\n");
}
result.zone().reset();
}
}
return 0;
}
Übrigens, wenn Sie das msgpack :: object-Format in ostream
( std :: cout
usw.) werfen, wird das Format ohne Erlaubnis formatiert und angezeigt, aber es ist wie oben beschrieben mühsam, den Wert programmgesteuert abzurufen. Das Verfahren wird als Beispiel beschrieben.
Recommended Posts