当前位置: 首页 > 知识库问答 >
问题:

在Firebase云函数中使用云fi恢复作为数据库的非常大的结果集/查询的替代解决方案

卜弘文
2023-03-14

我正在编写一个应用程序(使用Flutter和Firebase),该应用程序应该允许用户在特定时间获得提醒。

比如,我可以设置每天下午3点35分,我愿意被消息推送提醒,但只有在有事的时候。

为此,我创建了一个每隔5分钟调用一次的云函数。

首先,该函数对所有设置了当前时间提醒的用户进行数据库查询。

    const snapshot = await firestore.collection('reminders')
        .where('server.time', '==', time)
        .where('server.days', 'array-contains', day).get();

然后,该功能会检查每个想要提醒的提醒/用户是否需要执行某些操作。如果是这种情况,则会向相关用户发送Firebase云消息。

const result = await firestore.collection('tasks').where('date', '==', date)
    .orderBy('created').limit(1).get();
if (result.size === 1) {
    sendMessage();
}

我担心第一次数据库查询(活跃用户越来越多)会给我带来问题。之后的一切,我会尝试外包给单个云功能,然后可以并行处理(我希望这是可能的)。

如果在某个时刻有很多用户希望同时得到提醒,那么查询将花费太长时间。在最坏的情况下,如果查询时间超过540秒的功能限制,消息将晚发送几分钟,或者根本不发送。

我自己做了一些小测试,以获得稍微大一点的查询的性能的第一印象。

以下是我使用512MB内存的结果:

  • 100个文档=294 ms
  • 1,000个文档=2205 ms
  • 2,000个文档=1621 ms
  • 10,000个文档=5957 ms
  • 20,000个文档=10687 ms

以下是我在8GB内存下的结果:

  • 100份文件=122毫秒
  • 1000份文件=442毫秒
  • 2000份文件=566毫秒
  • 10000份文件=1932毫秒
  • 20000份文件=3884毫秒

较高的记忆力似乎有积极的影响。不过,我相信10万甚至100万份文件可能需要几分钟才能完成。

我认为用偏移量分页可能是一个解决方案。然后,我会为每批文档调用一个单独的云函数,例如50000个文档,然后进行实际的查询,并可以并行工作。

类似的东西:

export const sendReminders = firebase.pubsub.schedule('every 5 minutes').onRun(async () => {
    const batchSize = 500000;
    const documentCount = 1000000;  // could be saved in the database
    const batchCount = Math.ceil(documentCount / batchSize);
    for (let batch = 0; batch < batchCount; batch++) {
        handleBatch(batchSize, batch * batchSize);
    }
}

async function handleBatch(limit: number, offset: number, date: string) {
    const result = await firestore.collection('reminders').where('date', '==', date)
        .orderBy('created').limit(limit).offset(offset).get();
    for (const document in result.docs) {
        checkReminder(date, document);
    }
}

不幸的是,使用Firebase,您必须从偏移量中支付所有数据记录。因此,这似乎是一个非常昂贵的解决方案。因为整个问题只存在于大量数据中。

文档的大小当然会影响查询的速度。在我的例子中,一个文档大约有25个相对较小的字段,几乎没有数据。短字符串表示名称、引用其他文档的Id、一些布尔值等。没有什么特别的,文档中的数据量不是特别大。

有没有其他方法可以让我以不同的方式处理这个问题?这样我的应用程序或云功能不会随着用户数量的增加而变慢?

有没有人有过使用Cloud Firestore进行大型查询(100000到1000000个文档)需要多长时间的经验?

我将非常感谢任何帮助。

共有1个答案

万俟旭
2023-03-14

你是如何进行测试的(以及测试了多少次)?

100 documents = 294 ms
20,000 documents = 10.687 ms

2万份文件花费的时间少于100份。我不会质疑这一点,因为这可能是因为冷启动。对此可能有多种解决方案,当然,在尽可能长的时间内运行云功能和资源就是其中之一。

如果你仍然认为<代码> 540秒更少处理所有的数据,考虑使用谷歌云计算,因为它不会超时,并且可以使用谷歌云调度器定期在计算实例上运行函数。

如果你想坚持使用云功能,那么一个简单的策略就是将提醒分成N个批次,即添加一个字段{batch:N}。然后在同一时间表上运行N个计划函数,每个函数将查找批次号等于分配给它们的编号的文档。例如,第一个函数将查找批次1,依此类推。

非常大的查询(100,000到1,000,000个文档)需要多长时间?

我真的不能分享任何统计数据,但这也取决于你将在它们上运行什么样的过程以及这有多耗时。我不确定你指的是下载时间。

我通常使用第一种方法,因为它具有更大的灵活性和更少的冷启动(与其他流程一起一直运行)。您可以在云计算实例上使用cron节点包而不是调度器。

 类似资料:
  • 在以前的GCP项目中,我们部署了基于Python的云功能(使用gcloud cli),理想情况下,我们希望继续使用Python实现Firebase云功能。所以我的问题是: > 是否可以部署基于Python的Firebase云功能?如果没有: 我们是否可以回到使用gcloud cli部署基于Python的GCP云函数,并且仍然让它们作为Firestore触发器工作?

  • 在我正在开发的Firebase web应用程序中,我想从邮件地址获取用户ID。为此,我正在尝试编写一个云函数。但它不起作用,或者我没有正确使用它。以下是当前代码(基于我在网上找到的一些示例): 运行“firebase deploy”时,我看不到任何问题。然后,我尝试用各种方法测试该功能,就像我在本教程之后编写的演示应用程序一样。 例如(现有和不存在的邮件地址): 但在任何一种情况下,我都不会在We

  • 我正在尝试使用Firebase Cloud功能为iOS应用程序创建设备到设备推送通知。每当在数据库中的引用'/user-通知/{通知RecipientUid}/{挑战ID}'处创建新子节点时,我都想触发一个事件。这是我的index.js代码: 当在该位置的数据库中添加新的子数据库时,我收到此错误,“类型错误:函数.数据库.ref(...)。一次不是一个函数“,在 Firebase 控制台的函数日志

  • 我有一个firebase云函数(http请求),我想在其中更新firestore数据库中的文档 函数正在部署,正确,但每当我调用它不再打印任何内容。评论该部分打印“promise已解决”,我觉得我无法访问或使用错误的语法访问Firestore db,但我不明白为什么? Firebase日志正在打印: 函数执行开始 tr_。。。。。。。。(id) db调用前测试 函数执行耗时1103毫秒,完成状态代

  • 我正在使用Python3.6编写一个带有get方法的FlaskAPI,它将创建一个与GCP postgreSQL的连接,并执行一个简单的select查询。这里我希望我的函数应该返回postgreSQL查询的结果(行)。下面是我的代码: