Devo scrivere un gran numero di documenti su Firestore.
Qual è il modo più veloce per farlo in Node.js?
Devo scrivere un gran numero di documenti su Firestore.
Qual è il modo più veloce per farlo in Node.js?
Risposte:
TL; DR: il modo più rapido per eseguire la creazione di date in serie su Firestore è eseguire singole operazioni di scrittura parallele.
Scrivere 1.000 documenti su Firestore richiede:
~105.4s
quando si utilizzano operazioni di scrittura sequenziali individuali~ 2.8s
quando si utilizzano (2) operazioni di scrittura in batch~ 1.5s
quando si utilizzano operazioni di scrittura individuali paralleleEsistono tre modi comuni per eseguire un gran numero di operazioni di scrittura su Firestore.
Analizzeremo ciascuno a turno di seguito, utilizzando una matrice di dati del documento randomizzati.
Questa è la soluzione più semplice possibile:
async function testSequentialIndividualWrites(datas) {
while (datas.length) {
await collection.add(datas.shift());
}
}
Scriviamo ogni documento a turno, fino a quando non abbiamo scritto ogni documento. E aspettiamo che ogni operazione di scrittura venga completata prima di iniziare quella successiva.
La scrittura di 1.000 documenti richiede circa 105 secondi con questo approccio, quindi la velocità effettiva è di circa 10 scritture di documenti al secondo .
Questa è la soluzione più complessa.
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;
}
}
}
Puoi vedere che creiamo un BatchedWrite
oggetto chiamandobatch()
, riempilo fino alla sua capacità massima di 500 documenti, quindi scrivilo su Firestore. Diamo a ciascun documento un nome generato che è relativamente probabile che sia univoco (abbastanza buono per questo test).
La scrittura di 1.000 documenti richiede circa 2,8 secondi con questo approccio, quindi la velocità effettiva è di circa 357 scritture di documenti al secondo .
È un po 'più veloce rispetto alle singole scritture sequenziali. In effetti: molti sviluppatori usano questo approccio perché presumono che sia il più veloce, ma poiché i risultati di cui sopra hanno già dimostrato che ciò non è vero. E il codice è di gran lunga il più complesso, a causa del vincolo di dimensione sui batch.
La documentazione di Firestore dice questo sulle prestazioni per l'aggiunta di molti dati :
Per l'immissione di dati in blocco, utilizzare una libreria client del server con scritture individuali parallelizzate. Le scritture in batch funzionano meglio delle scritture serializzate ma non meglio delle scritture parallele.
Possiamo metterlo alla prova con questo codice:
async function testParallelIndividualWrites(datas) {
await Promise.all(datas.map((data) => collection.add(data)));
}
Questo codice add
dà il via alle operazioni il più velocemente possibile e quindi usa Promise.all()
per attendere fino a quando non sono finite tutte. Con questo approccio le operazioni possono essere eseguite in parallelo.
La scrittura di 1.000 documenti richiede circa 1,5 secondi con questo approccio, quindi la velocità effettiva è di circa 667 scritture di documenti al secondo .
La differenza non è così grande come tra i primi due approcci, ma è ancora oltre 1,8 volte più veloce delle scritture in batch.
Alcune note:
add()
non fa altro che generare un ID univoco (puramente lato client), seguito da set()
un'operazione. Quindi i risultati dovrebbero essere gli stessi. Se non è quello che osservi, pubblica una nuova domanda con il caso minimo che riproduce ciò che hai provato.