Firestore 获取数据时性能缓慢的问题 [英] Firestore slow performance issue on getting data

查看:29
本文介绍了Firestore 获取数据时性能缓慢的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having slow performance issues with Firestore while retrieving basic data stored in a document compared to the realtime database with 1/10 ratio.

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

Using Firestore, it takes an average of 3000 ms on the first call

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

使用实时数据库,第一次调用平均需要 300 毫秒

Using the realtime database, it takes an average of 300 ms on the first call

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

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

This is a screenshot of the network console :

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

I'm running the Javascript SDK v4.50 with AngularFire2 v5.0 rc.2.

有人遇到过这个问题吗?

Did anyone experience this issue ?

推荐答案

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

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

Similar to some other commenters, I've also noticed a slower response on the first get request (with subsequent requests taking ~100ms). For me it's not as bad as 30s, but maybe around 2-3s when I have good connectivity, which is enough to provide a bad user experience when my app starts up.

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

Firebase have advised that they're aware of this "cold start" issue and they're working on a long term fix for it - no ETA unfortunately. I think it's a separate issue that when I have poor connectivity, it can take ages (over 30s) before get requests decide to read from cache.

虽然 Firebase 解决了所有这些问题,但我已经开始使用新的 disableNetwork()enableNetwork() 方法(在 Firestore v0.10.0 中可用)来手动控制Firebase 的在线/离线状态.尽管我在代码中使用它时必须非常小心,因为有一个 Firestore 错误会在某些情况下导致崩溃.

Whilst Firebase fix all these issues, I've started using the new disableNetwork() and enableNetwork() methods (available in Firestore v0.10.0) to manually control the online/offline state of Firebase. Though I've had to be very careful where I use it in my code, as there's a Firestore bug that can cause a crash under certain scenarios.

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

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

It seems the slow performance issue has now been fixed. I've re-run the tests described below and the time it takes for Firestore to return the 100 documents now seems to be consistently around 100ms.

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

Not sure if this was a fix in the latest SDK v0.9.2 or if it was a backend fix (or both), but I suggest everyone updates their Firebase pods. My app is noticeably more responsive - similar to the way it was on the Realtime DB.

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

I've also discovered Firestore to be much slower than Realtime DB, especially when reading from lots of documents.

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

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

I set up a test project in iOS Swift using both RTDB and Firestore and ran 100 sequential read operations on each. For the RTDB, I tested the observeSingleEvent and observe methods on each of the 100 top level nodes. For Firestore, I used the getDocument and addSnapshotListener methods at each of the 100 documents in the TestCol collection. I ran the tests with disk persistence on and off. Please refer to the attached image, which shows the data structure for each database.

我在同一设备和稳定的 wifi 网络上为每个数据库运行了 10 次测试.在每次新运行之前,现有的观察者和侦听器都会被销毁.

I ran the test 10 times for each database on the same device and a stable wifi network. Existing observers and listeners were destroyed before each new run.

实时数据库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)")
        }
    }
}

实时数据库观察方法:

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 时间戳.我取了初始时间戳和最后一个时间戳之间的差异来返回.

Each method essentially prints the unix timestamp in milliseconds when the method starts executing and then prints another unix timestamp when each read operation returns. I took the difference between the initial timestamp and the last timestamp to return.

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

结果 - 启用磁盘持久性:

数据结构:

当 Firestore getDocument/addSnapshotListener 方法卡住时,它似乎卡住了大约 30 秒的倍数的持续时间.也许这可以帮助 Firebase 团队隔离它在 SDK 中卡住的位置?

When the Firestore getDocument / addSnapshotListener methods get stuck, it seems to get stuck for durations that are roughly multiples of 30 seconds. Perhaps this could help the Firebase team isolate where in the SDK it's getting stuck?

这篇关于Firestore 获取数据时性能缓慢的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆