Tôi cần phải viết một số lượng lớn tài liệu cho Firestore.
Cách nhanh nhất để làm điều này trong Node.js là gì?
Tôi cần phải viết một số lượng lớn tài liệu cho Firestore.
Cách nhanh nhất để làm điều này trong Node.js là gì?
Câu trả lời:
TL; DR: Cách nhanh nhất để thực hiện tạo ngày hàng loạt trên Firestore là bằng cách thực hiện các thao tác ghi riêng lẻ song song.
Viết 1.000 tài liệu cho Firestore mất:
~105.4s
khi sử dụng các thao tác ghi riêng lẻ tuần tự~ 2.8s
khi sử dụng (2) thao tác ghi theo đợt~ 1.5s
khi sử dụng các thao tác ghi riêng lẻ song songCó ba cách phổ biến để thực hiện một số lượng lớn thao tác ghi trên Firestore.
Chúng tôi sẽ điều tra lần lượt từng cái bên dưới, sử dụng một loạt dữ liệu tài liệu ngẫu nhiên.
Đây là giải pháp đơn giản nhất có thể:
async function testSequentialIndividualWrites(datas) {
while (datas.length) {
await collection.add(datas.shift());
}
}
Chúng tôi lần lượt viết từng tài liệu cho đến khi chúng tôi viết mọi tài liệu. Và chúng tôi chờ cho mỗi thao tác ghi hoàn thành trước khi bắt đầu thao tác ghi tiếp theo.
Viết 1.000 tài liệu mất khoảng 105 giây với phương pháp này, do đó, thông lượng là khoảng 10 tài liệu viết mỗi giây .
Đây là giải pháp phức tạp nhất.
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;
}
}
}
Bạn có thể thấy rằng chúng tôi tạo một BatchedWrite
đối tượng bằng cách gọi batch()
, điền vào đó cho đến khi dung lượng tối đa 500 tài liệu của nó, sau đó viết nó cho Firestore. Chúng tôi cung cấp cho mỗi tài liệu một tên được tạo tương đối có khả năng là duy nhất (đủ tốt cho thử nghiệm này).
Viết 1.000 tài liệu mất khoảng 2,8 giây với phương pháp này, do đó, thông lượng là khoảng 357 tài liệu viết mỗi giây .
Đó là khá nhanh hơn một chút so với viết cá nhân tuần tự. Trên thực tế: nhiều nhà phát triển sử dụng phương pháp này vì họ cho rằng nó nhanh nhất, nhưng vì kết quả ở trên đã cho thấy điều này không đúng. Và mã là phức tạp nhất, do hạn chế kích thước trên các lô.
Tài liệu của Firestore nói điều này về hiệu suất để thêm nhiều dữ liệu :
Để nhập dữ liệu số lượng lớn, hãy sử dụng thư viện máy khách với ghi riêng lẻ. Viết theo lô thực hiện tốt hơn ghi tuần tự nhưng không tốt hơn ghi song song.
Chúng tôi có thể thử nghiệm điều đó với mã này:
async function testParallelIndividualWrites(datas) {
await Promise.all(datas.map((data) => collection.add(data)));
}
Mã này khởi add
động các hoạt động nhanh nhất có thể, và sau đó sử dụng Promise.all()
để đợi cho đến khi tất cả hoàn thành. Với cách tiếp cận này, các hoạt động có thể chạy song song.
Viết 1.000 tài liệu mất khoảng 1,5 giây với phương pháp này, do đó, thông lượng là khoảng 667 tài liệu viết mỗi giây .
Sự khác biệt không lớn bằng giữa hai cách tiếp cận đầu tiên, nhưng nó vẫn nhanh hơn 1,8 lần so với cách viết theo đợt.
Một vài lưu ý:
add()
không làm gì khác hơn là tạo một ID duy nhất (hoàn toàn là phía máy khách), theo sau là một set()
thao tác. Vì vậy, kết quả nên giống nhau. Nếu đó không phải là những gì bạn quan sát, hãy đăng một câu hỏi mới với trường hợp tối thiểu tái tạo những gì bạn đã thử.