我在Python 3.7中有一个Cloud函数,可以将小文档写入/更新到Firestore。每个文档都有一个user_id作为document_id,还有两个字段:一个时间戳和一个带有三个键值对象的map(一个字典(,它们都很小。
这是我用来编写/更新Firestore:的代码
doc_ref = db.collection(u'my_collection').document(user['user_id'])
date_last_seen=datetime.combine(date_last_seen, datetime.min.time())
doc_ref.set({u'map_field': map_value, u'date_last_seen': date_last_seen})
我的目标是每天调用这个函数一次,并编写/更新大约50万个文档。我尝试了以下测试,每一个测试我都包括执行时间:
测试A:将输出处理为1000个文档。不写入/更新Firestore->2秒
测试B:将输出处理为1000个文档。写入/更新Firestore->~1分3秒
测试C:将输出处理为5000个文档。不写入/更新Firestore->3秒
测试D:将输出处理为5000个文档。写入/更新Firestore->约3分12秒
我的结论是:编写/更新Firestore消耗了我99%以上的计算时间。
问题:如何每天高效地编写/更新约50万份文档?
如果不了解实际要编写的数据的详细信息,就不可能规定一个单独的操作过程。我强烈建议您阅读有关Firestore最佳实践的文档。它会让你知道你可以做些什么来避免重写负载的问题。
基本上,你会想避免这些情况,如文档中所述:
读取、写入和删除率高,文档范围窄
避免高读写率以字典方式关闭文档,否则您的应用程序将出现争用错误。这个问题是称为热点,您的应用程序可能会经历热点如果它执行以下任何操作:
以非常高的速率创建新文档,并分配自己单调递增的ID。
Cloud Firestore使用分散算法分配文档ID。如果你创建了新的,你就不应该在写入时遇到热点使用自动文档ID的文档。
在文档较少的集合中以高速率创建新文档。
以非常高的速率创建具有单调递增字段(如时间戳(的新文档。
以高速率删除集合中的文档。
以非常高的速率写入数据库,而不会逐渐增加流量。
我不会重复那个文档中的所有建议。你需要知道的是:由于Firestore的构建方式是为了大规模扩展,所以你向其中写入数据的速度受到了限制。你必须逐步扩展这一事实可能是你无法解决的主要问题。
我通过批处理查询满足了我的需求。但根据Firestore的文档,还有另一种更快的方法:
注意:对于批量数据输入,使用带有并行化的单个写入。批处理写入的性能优于串行化写入,但并不比并行写入好。你应该使用用于批量数据操作的服务器客户端库,而不是移动/webSDK。
我还建议在stackoverflow中查看这篇文章,并在Node.js 中提供示例