Firestore 获取数据时性能缓慢的问题

2023-12-08

与实时数据库相比,我在检索文档中存储的基本数据时遇到了 Firestore 性能缓慢的问题(比率为 1/10)。

使用 Firestore,第一次调用平均需要 3000 毫秒

 this.db.collection(‘testCol’)
   .doc(‘testDoc’)
   .valueChanges().forEach((data) => {
     console.log(data);//3000 ms later
 });

使用实时数据库,首次调用平均耗时300ms

 this.db.database.ref(‘/test’).once(‘value’).then(data => {
     console.log(data); //300ms later
 });

这是网络控制台的屏幕截图:

Firestore slow performance issue get Data

我正在使用 AngularFire2 v5.0 rc.2 运行 Javascript SDK v4.50。

有人遇到过这个问题吗?


更新:2018 年 2 月 12 日 - iOS Firestore SDK v0.10.0

与其他一些评论者类似,我也注意到第一个 get 请求的响应速度较慢(后续请求大约需要 100 毫秒)。对我来说,它没有 30 秒那么糟糕,但当我连接良好时,可能需要大约 2-3 秒,这足以在我的应用程序启动时提供糟糕的用户体验。

Firebase 表示他们已经意识到这个“冷启动”问题,并且正在努力解决该问题 - 不幸的是,没有预计到达时间。我认为这是一个单独的问题,当我的连接较差时,获取请求可能需要很长时间(超过 30 秒)才能决定从缓存中读取。

虽然 Firebase 解决了所有这些问题,但我已经开始使用新的disableNetwork() and enableNetwork()方法(在 Firestore v0.10.0 中提供)手动控制 Firebase 的在线/离线状态。虽然我不得不这样very请小心我在代码中使用它的地方,因为存在一个 Firestore 错误,在某些情况下可能会导致崩溃。


更新:2017 年 11 月 15 日 - iOS Firestore SDK v0.9.2

看来性能缓慢的问题现已得到解决。我重新运行了下面描述的测试,Firestore 返回 100 个文档所需的时间现在似乎始终在 100 毫秒左右。

不确定这是否是最新 SDK v0.9.2 中的修复或后端修复(或两者),但我建议每个人都更新其 Firebase pod。我的应用程序的响应速度明显更快 - 类似于实时数据库上的方式。


我还发现 Firestore 比实时数据库慢得多,尤其是在读取大量文档时。

更新的测试(使用最新的 iOS Firestore SDK v0.9.0):

我使用 RTDB 和 Firestore 在 iOS Swift 中设置了一个测试项目,并在每个项目上运行了 100 个顺序读取操作。对于 RTDB,我在 100 个顶级节点中的每一个上测试了observeSingleEvent 和observe 方法。对于 Firestore,我对 TestCol 集合中的 100 个文档中的每一个都使用了 getDocument 和 addSnapshotListener 方法。我在打开和关闭磁盘持久性的情况下运行了测试。请参阅附图,其中显示了每个数据库的数据结构。

我在同一设备和稳定的 WiFi 网络上对每个数据库运行了 10 次测试。现有的观察者和听众在每次新运行之前都会被销毁。

实时数据库observeSingleEvent方法:

func rtdbObserveSingle() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from RTDB at: \(start)")

    for i in 1...100 {
        Database.database().reference().child(String(i)).observeSingleEvent(of: .value) { snapshot in
            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            let data = snapshot.value as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

实时DB观察方法:

func rtdbObserve() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from RTDB at: \(start)")

    for i in 1...100 {
        Database.database().reference().child(String(i)).observe(.value) { snapshot in
            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            let data = snapshot.value as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

Firestore getDocument 方法:

func fsGetDocument() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from FS at: \(start)")

    for i in 1...100 {
        Firestore.firestore().collection("TestCol").document(String(i)).getDocument() { document, error in

            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            guard let document = document, document.exists && error == nil else {
                print("Error: \(error?.localizedDescription ?? "nil"). Returned at: \(time)")
                return
            }
            let data = document.data() as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

Firestore addSnapshotListener 方法:

func fsAddSnapshotListener() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from FS at: \(start)")

    for i in 1...100 {
        Firestore.firestore().collection("TestCol").document(String(i)).addSnapshotListener() { document, error in

            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            guard let document = document, document.exists && error == nil else {
                print("Error: \(error?.localizedDescription ?? "nil"). Returned at: \(time)")
                return
            }
            let data = document.data() as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

每个方法本质上都会在方法开始执行时打印以毫秒为单位的 unix 时间戳,然后在每个读取操作返回时打印另一个 unix 时间戳。我获取了初​​始时间戳和最后一个时间戳之间的差异来返回。

结果 - 磁盘持久性已禁用:

Disk persistence disabled

结果 - 启用磁盘持久性:

Disk persistence enabled

数据结构:

Data Structure

当 Firestore getDocument / addSnapshotListener 方法卡住时,卡住的持续时间大约为 30 秒的倍数。也许这可以帮助 Firebase 团队隔离 SDK 中遇到问题的位置?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Firestore 获取数据时性能缓慢的问题 的相关文章

  • 在javascript中使用“return !0”有什么意义吗?

    如果您转到谷歌结果页面并运行rwt toString 你会看到这个函数的返回调用是 return 0 我想不出任何理由为什么这不会总是如此true 这只是一个简写吗true 还是还有更多事情发生 总是如此 但下载需要 2 个字节 0是 2
  • 如何根据按钮单击折叠和展开 Kendo UI 树视图中的所有树节点?

    这是行不通的 您可以使用此代码 1 崩溃 折叠kendoTree查看文档 http docs kendoui com api web treeview methods collapse treeview kendoTreeView var
  • 如何使用 axios / jest 测试失败的请求

    我创建了一个非常小的应用程序 如果您传递硬币和数量 它可以计算为某些加密货币支付的总价格 我想测试错误 但我总是收到 收到的承诺已解决而不是被拒绝 我相信这是因为如果 url 错误 axios 仍然会解决承诺 我遇到的第二个问题是 我尝试测
  • 使用闭包和自调用函数制作计数器

    我想知道为什么这段代码不起作用 var uniqueInteger function var counter 0 return function return counter console log uniqueInteger 0 cons
  • 如何从表中选择所有偶数 id?

    我想从 MySQL 数据库的表中选择所有甚至帖子 ID 然后显示它们 我还想获取所有带有奇怪 id 的帖子并将它们显示在其他地方 我想使用 PHP 来完成此操作 因为这是我使用的服务器端语言 或者 我是否必须选择所有帖子 然后使用 Java
  • JavaScript 变量赋值与 OR 对比 if 检查[重复]

    这个问题在这里已经有答案了 在 JavaScript 中 我最近意识到你可以使用 OR 赋值的逻辑运算符 我想知道这是否被认为是不好的做法 特别是 我有一些具有可选数组输入的函数 如果输入是null or undefined我应该将它设置为
  • 在 JavaScript 中比较表单中的两个数字

    当我尝试比较不同的数字时 数字发生变化 但文本部分保持不变 这只发生在较大 较小的情况下 而不会发生在 NaN 或相等的情况下 这是我的代码 function check var a document getElementById a va
  • 提交前验证表单(比检查空字段更复杂)

    我有一个包含时间输入的表单 具体来说 开放时间和结束时间 当按下提交按钮时 它会转到一个 php 页面 其中这些输入将添加到数据库中 在允许提交表单之前我想检查一些事情 例如 我想确保开始时间早于 小于 结束时间 这是表格 Opens
  • 使用 jQuery 仅从字符串末尾修剪空格

    我知道 jQuery trim 函数 但我需要的是一种仅从字符串末尾修剪空格的方法 而不是开头 So str this is a string 会成为 str this is a string 有什么建议么 Thanks 您可以使用正则表达
  • 光滑的轮播缓动示例

    我正在使用 Slick Carousel http kenwheeler github io slick http kenwheeler github io slick 但不知道如何合并不同的幻灯片切换 有人有例子可以分享吗 这是我目前拥有
  • 点击问题:动态生成的链接不触发点击功能

    下面是两个代码片段 由于某种原因什么也没有发生 但来自同一个 JS 文件的其他 jQuery 函数在带有 UL 的页面上执行得很好 这是在盯着我看吗 ul class paganation li 1 li li a href 2 a li
  • 空 URL 哈希导致页面在 js 事件上跳转

    我有一个带有下一个和上一个按钮的照片库 如果我的某个 javascript 方法由于某种原因被破坏 那么当单击其中一个按钮时 它会向 url 添加一个哈希值 即 www google com 我知道可以给散列一个 div id 来跳转到页面
  • 对象数组 - 在 Vue.js 生态系统中更新对象的正确方法

    我不确定问题到底出在哪里 但我会看看是否有人可以帮助我理解我的代码出了什么问题 我正在利用 Vuex 商店来跟踪某些不断变化的状态 我这样做如下 import Vue from vue import Vuex from vuex Vue u
  • 元素中优先考虑 ngclick 而非 nghref

    tl dr 如何强制 Angular 只执行 ngclick 指令 a 元素而不清空 删除href 我的网站在某些元素上有一些自定义行为 模式打开 位置栏更新等 但对于 SEO 索引我also需要它成为一个 a 元素与href包含有效链接的
  • Javascript 选择 onchange='this.form.submit()'

    我有一个带有选择和一些文本输入的表单 我希望在更改选择时提交表单 使用以下方法可以正常工作 onchange this form submit 但是 如果表单还包含提交按钮 则当选择更改时 表单不会提交 我猜有某种冲突 我在这里有什么选择
  • 常规 JavaScript 可以与 jQuery 混合使用吗?

    例如 我可以采用这个脚本 来自 Mozilla 教程 https developer mozilla org en Canvas tutorial Basic usage
  • 使用 onAuthStateChanged 通过 Flutter 登录 Firebase

    在 Flutter 之外 当我实现 firebase 身份验证时 我总是使用 firebase 提供的 onAuthStateChanged 侦听器来确定用户是否登录并做出相应响应 我正在尝试使用 flutter 做类似的事情 但我可以找到
  • 使用 jQuery Tablesorter 操作后如何恢复当前页面?

    我正在使用 tablesorter 但无法找到有关插件 tablesorter 寻呼机的任何文档 问题是我有一个显示一些数据的表 并且在每一行中都有一个删除链接 该链接附加了要删除的元素的唯一标识符 显然 是否可以保存我正在删除的页面 然后
  • 错误:创建 React Native 项目版本 0.59.9 时找不到 template.config.js

    当我尝试创建 React Native 项目版本 0 59 9 时 出现以下错误 错误错误 无法在 react native 模板中找到 var folders zc h93bvpb573q24 5ynvgkn1wc0000gn T rnc
  • Serviceworker Bug event.respondWith

    我的 serviceworker 的逻辑是 当发生获取事件时 它首先获取包含一些布尔值 而不是 event request url 的端点 并根据我正在调用的值检查该值event respondWith 对于当前的获取事件 我正在提供来自缓

随机推荐