Ich muss eine große Anzahl von Dokumenten an Firestore schreiben.
Was ist der schnellste Weg, dies in Node.js zu tun?
Ich muss eine große Anzahl von Dokumenten an Firestore schreiben.
Was ist der schnellste Weg, dies in Node.js zu tun?
Antworten:
TL; DR: Der schnellste Weg zur Erstellung von Massendaten im Firestore besteht darin, parallele Einzelschreibvorgänge durchzuführen.
Das Schreiben von 1.000 Dokumenten an Firestore erfordert:
~105.4s
bei Verwendung sequentieller Einzelschreibvorgänge~ 2.8s
bei Verwendung von (2) Stapelschreibvorgängen~ 1.5s
bei Verwendung paralleler EinzelschreibvorgängeEs gibt drei gängige Methoden, um eine große Anzahl von Schreibvorgängen im Firestore auszuführen.
Wir werden sie nacheinander anhand eines Arrays randomisierter Dokumentdaten untersuchen.
Dies ist die einfachste mögliche Lösung:
async function testSequentialIndividualWrites(datas) {
while (datas.length) {
await collection.add(datas.shift());
}
}
Wir schreiben jedes Dokument der Reihe nach, bis wir jedes Dokument geschrieben haben. Und wir warten, bis jeder Schreibvorgang abgeschlossen ist, bevor wir mit dem nächsten beginnen.
Das Schreiben von 1.000 Dokumenten dauert bei diesem Ansatz ungefähr 105 Sekunden, sodass der Durchsatz ungefähr 10 Dokumentschreibvorgänge pro Sekunde beträgt .
Dies ist die komplexeste Lösung.
async function testBatchedWrites(datas) {
let batch = admin.firestore().batch();
let count = 0;
while (datas.length) {
batch.set(collection.doc(Math.random().toString(36).substring(2, 15)), datas.shift());
if (++count >= 500 || !datas.length) {
await batch.commit();
batch = admin.firestore().batch();
count = 0;
}
}
}
Sie können sehen, dass wir ein BatchedWrite
Objekt erstellen, indem Sie es aufrufen batch()
, es bis zu seiner maximalen Kapazität von 500 Dokumenten füllen und es dann in Firestore schreiben. Wir geben jedem Dokument einen generierten Namen, der relativ wahrscheinlich eindeutig ist (gut genug für diesen Test).
Das Schreiben von 1.000 Dokumenten dauert bei diesem Ansatz ungefähr 2,8 Sekunden, sodass der Durchsatz ungefähr 357 Dokumentschreibvorgänge pro Sekunde beträgt .
Das ist ziemlich viel schneller als bei den sequentiellen einzelnen Schreibvorgängen. Tatsächlich verwenden viele Entwickler diesen Ansatz, weil sie davon ausgehen, dass er am schnellsten ist. Wie die obigen Ergebnisse bereits gezeigt haben, ist dies jedoch nicht der Fall. Und der Code ist aufgrund der Größenbeschränkung für Stapel bei weitem der komplexeste.
In der Firestore-Dokumentation wird Folgendes über die Leistung beim Hinzufügen vieler Daten angegeben :
Verwenden Sie für die Eingabe von Massendaten eine Server-Client-Bibliothek mit parallelisierten einzelnen Schreibvorgängen. Batch-Schreibvorgänge sind besser als serialisierte Schreibvorgänge, jedoch nicht besser als parallele Schreibvorgänge.
Wir können das mit diesem Code testen:
async function testParallelIndividualWrites(datas) {
await Promise.all(datas.map((data) => collection.add(data)));
}
Dieser Code startet die add
Vorgänge so schnell wie möglich und Promise.all()
wartet dann, bis alle abgeschlossen sind. Mit diesem Ansatz können die Operationen parallel ausgeführt werden.
Das Schreiben von 1.000 Dokumenten dauert bei diesem Ansatz ungefähr 1,5 Sekunden, sodass der Durchsatz ungefähr 667 Dokumentschreibvorgänge pro Sekunde beträgt .
Der Unterschied ist nicht annähernd so groß wie zwischen den ersten beiden Ansätzen, aber immer noch mehr als 1,8-mal schneller als bei Batch-Schreibvorgängen.
Ein paar Anmerkungen:
add()
wird lediglich eine eindeutige ID (rein clientseitig) generiert, gefolgt von einer set()
Operation. Die Ergebnisse sollten also gleich sein. Wenn Sie dies nicht beobachten, stellen Sie eine neue Frage mit dem Minimalfall, der das reproduziert, was Sie versucht haben.