Problem mit langsamer Leistung des Firestores beim Abrufen von Daten

78

Ich habe langsame Leistungsprobleme mit Firestore beim Abrufen der in einem Dokument gespeicherten Basisdaten im Vergleich zur Echtzeitdatenbank mit einem Verhältnis von 1/10.

Bei Verwendung von Firestore dauert der erste Anruf durchschnittlich 3000 ms

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

Bei Verwendung der Echtzeitdatenbank dauert der erste Aufruf durchschnittlich 300 ms

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

Dies ist ein Screenshot der Netzwerkkonsole:

Firestore langsame Leistung Problem erhalten Daten

Ich führe das Javascript SDK v4.50 mit AngularFire2 v5.0 rc.2 aus.

Hat jemand dieses Problem erlebt?

Olivier P.
quelle
Welche Leistung sehen Sie, wenn Sie einen zweiten Anruf tätigen (ein anderes Dokument / eine andere Sammlung)? Sehen Sie das gleiche Problem, wenn Sie kein Winkelfeuer verwenden?
Sam Stern
Ich habe eine ähnliche Erfahrung. Der erste Anruf ist etwas langsam, manchmal 5-10 Sekunden. Ich mache eine Chat-App - die Zustellung der ersten Nachricht dauert eine Weile, die folgenden sind jedoch fast augenblicklich. Firestore ist noch Beta, sie werden wahrscheinlich immer noch Macken aussortieren.
Xenetics
1
Ähnliche Erfahrungen hier. First onSnapShot nimmt eine unglaubliche Zeit in Anspruch - bis zu 2 Minuten für einige Benutzer, die unsere App unbrauchbar machen
wizloc
Gleiches Problem, ziemlich frustrierend. Einige berichten, dass beim Schreiben die "hängengebliebenen" Abfragen freigegeben werden.
DarkNeuron
Gleiches Problem, bis zu 1,5 Minuten mit einem einfachen collection.get (Dokument)
aMarCruz

Antworten:

44

UPDATE: 12. Februar 2018 - iOS Firestore SDK v0.10.0

Ähnlich wie bei einigen anderen Kommentatoren habe ich auch bei der ersten Abrufanforderung eine langsamere Antwort festgestellt (wobei nachfolgende Anforderungen ~ 100 ms dauern). Für mich ist es nicht so schlimm wie 30s, aber vielleicht 2-3 Sekunden, wenn ich eine gute Konnektivität habe, was ausreicht, um beim Starten meiner App eine schlechte Benutzererfahrung zu bieten.

Firebase hat mitgeteilt, dass sie sich dieses "Kaltstart" -Problems bewusst sind und an einer langfristigen Lösung dafür arbeiten - leider keine ETA. Ich denke, es ist ein separates Problem, dass es bei schlechter Konnektivität Ewigkeiten (über 30 Sekunden) dauern kann, bis sich Anfragen zum Lesen aus dem Cache entscheiden.

Während Firebase all diese Probleme behebt, habe ich begonnen, die neuen disableNetwork()und enableNetwork()Methoden (verfügbar in Firestore v0.10.0) zu verwenden, um den Online- / Offline-Status von Firebase manuell zu steuern. Obwohl ich sehr vorsichtig sein musste, wo ich es in meinem Code verwende, da es einen Firestore-Fehler gibt, der unter bestimmten Umständen einen Absturz verursachen kann.


UPDATE: 15. November 2017 - iOS Firestore SDK v0.9.2

Es scheint, dass das Problem mit der langsamen Leistung jetzt behoben wurde. Ich habe die unten beschriebenen Tests erneut ausgeführt, und die Zeit, die Firestore benötigt, um die 100 Dokumente zurückzugeben, scheint nun konstant bei 100 ms zu liegen.

Ich bin mir nicht sicher, ob dies ein Fix im neuesten SDK v0.9.2 war oder ob es ein Backend-Fix (oder beides) war, aber ich schlage vor, dass jeder seine Firebase-Pods aktualisiert. Meine App reagiert deutlich schneller - ähnlich wie in der Echtzeit-Datenbank.


Ich habe auch festgestellt, dass Firestore viel langsamer als Realtime DB ist, insbesondere beim Lesen aus vielen Dokumenten.

Aktualisierte Tests (mit dem neuesten iOS Firestore SDK v0.9.0):

Ich habe ein Testprojekt in iOS Swift mit RTDB und Firestore eingerichtet und jeweils 100 sequentielle Lesevorgänge ausgeführt. Für die RTDB habe ich das ObservSingleEvent getestet und Methoden auf jedem der 100 Knoten der obersten Ebene beobachtet. Für Firestore habe ich die Methoden getDocument und addSnapshotListener für jedes der 100 Dokumente in der TestCol-Auflistung verwendet. Ich habe die Tests mit ein- und ausgeschalteter Festplattenpersistenz ausgeführt. Bitte beachten Sie das beigefügte Bild, das die Datenstruktur für jede Datenbank zeigt.

Ich habe den Test 10 Mal für jede Datenbank auf demselben Gerät und einem stabilen WLAN-Netzwerk ausgeführt. Bestehende Beobachter und Zuhörer wurden vor jedem neuen Lauf zerstört.

Echtzeit-DB-ObservSingleEvent-Methode:

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)")
        }
    }
}

Echtzeit-DB-Beobachtungsmethode:

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-Methode:

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-Methode:

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)")
        }
    }
}

Jede Methode druckt den Unix-Zeitstempel im Wesentlichen in Millisekunden, wenn die Methode ausgeführt wird, und druckt dann einen weiteren Unix-Zeitstempel, wenn jede Leseoperation zurückkehrt. Ich habe die Differenz zwischen dem anfänglichen Zeitstempel und dem letzten zurückgegebenen Zeitstempel genommen.

ERGEBNISSE - Festplattenpersistenz deaktiviert:

Festplattenpersistenz deaktiviert

ERGEBNISSE - Festplattenpersistenz aktiviert:

Festplattenpersistenz aktiviert

Datenstruktur:

Datenstruktur

Wenn die Methoden getDocument / addSnapshotListener von Firestore nicht mehr funktionieren, scheint sie für eine Dauer von ungefähr einem Vielfachen von 30 Sekunden hängen zu bleiben. Vielleicht könnte dies dem Firebase-Team helfen, herauszufinden, wo im SDK es stecken bleibt?

Saul
quelle
2
Der Firestore ist also teurer und viel langsamer.
Ich
6
[Firebaser hier] Vielen Dank, dass Sie sich die Zeit genommen haben, so detaillierte Daten bereitzustellen. Wir wissen das immer zu schätzen. Das Problem ist nicht, dass das System "langsamer" ist, sondern dass eine sehr kleine Anzahl von Abfragen hängen bleibt oder viel Zeit benötigt, um zurückzukehren. Wir haben in Kürze einige Korrekturen, von denen wir glauben, dass sie die Situation verbessern werden.
Sam Stern
1
Vielen Dank, dass Sie uns auf dem Laufenden halten. Ich habe einige neue Ergebnisse für das neueste Firestore SDK v0.9.0 hinzugefügt, die Ihrem Team helfen könnten, die Ursache des Problems zu ermitteln. Ich habe auch ein anderes Problem mit dem Snapshot-Listener festgestellt : stackoverflow.com/questions/46710371/… Die Hauptursache kann mit diesem Thema zusammenhängen oder nicht, aber es wäre großartig, wenn das Firebase-Team einen Blick darauf werfen könnte . Danke vielmals!
Saul
3
Wir haben auch "steckengebliebene" Abfragen im Web-SDK. Hängt für 10-20 Sekunden, dann kommen Daten an (auf v4.8.0).
DarkNeuron
1
Ich habe dies kürzlich bemerkt und mich bei Firebase gemeldet. Sie sind sich des Problems des "Kaltstarts" bewusst und arbeiten an einer Lösung. In der Zwischenzeit versuche ich eine Problemumgehung, die in meinem obigen Update beschrieben ist, und ich hatte unterschiedliche Erfolge damit.
Saul
20

Aktualisierungsdatum 02. März 2018

Es sieht so aus, als wäre dies ein bekanntes Problem, und die Ingenieure von Firestore arbeiten an einer Lösung. Nach einigen E-Mail-Austauschen und Code-Sharing mit einem Firestore-Techniker zu diesem Thema war dies seine heutige Antwort.

"Sie haben tatsächlich Recht. Bei weiteren Überprüfungen ist diese Langsamkeit der getDocuments () - API ein bekanntes Verhalten in der Cloud Firestore-Beta. Unsere Ingenieure sind sich dieses Leistungsproblems bewusst, das als" Kaltstart "gekennzeichnet ist, aber machen Sie sich keine Sorgen, während wir dies tun Unser Bestes, um die Leistung von Firestore-Abfragen zu verbessern.

Wir arbeiten bereits an einer langfristigen Lösung, aber ich kann derzeit keine Zeitpläne oder Einzelheiten mitteilen. Während sich Firestore noch in der Beta-Phase befindet, werden weitere Verbesserungen erwartet. "

Hoffentlich wird dies bald ausgeschaltet.


Verwenden von Swift / iOS

Nach ungefähr 3 Tagen scheint das Problem definitiv get () zu sein, dh .getDocuments und .getDocument. Dinge, von denen ich dachte , dass sie die extremen, aber zeitweise auftretenden Verzögerungen verursachen, scheinen aber nicht der Fall zu sein:

  1. Nicht so gute Netzwerkkonnektivität
  2. Wiederholte Aufrufe durch Schleifen über .getDocument ()
  3. Verketten von get () -Aufrufen
  4. Firestore Kaltstart
  5. Abrufen mehrerer Dokumente (Das Abrufen eines kleinen Dokuments verursachte Verzögerungen von 20 Sekunden.)
  6. Caching (Ich habe die Offline-Persistenz deaktiviert, aber dies hat nichts bewirkt.)

Ich konnte all dies ausschließen, da ich bemerkte, dass dieses Problem nicht bei jedem Firestore-Datenbankaufruf auftrat, den ich tätigte. Nur Abfragen mit get (). Für Kicks habe ich .getDocument durch .addSnapshotListener ersetzt, um meine Daten und Voila abzurufen. Sofortiges Abrufen jedes Mal einschließlich des ersten Anrufs. Kein Kaltstart. Bisher keine Probleme mit dem .addSnapshotListener, nur getDocument (s).

Im Moment lösche ich einfach das .getDocument (), wo die Zeit entscheidend ist, und ersetze es durch .addSnapshotListener und verwende es dann

for document in querySnapshot!.documents{
// do some magical unicorn stuff here with my document.data()
}

... um in Bewegung zu bleiben, bis dies von Firestore geklärt wird.

Terrence
quelle
Ich sehe das gleiche Verhalten auch, aber nur in Android. Im Moment greife ich auch auf Schnappschüsse zurück. Es ist jedoch gut, wenn die Leistung beim Abrufen von Abfragen konsistent ist.
Sowdri
Ich sehe auch eine langsame Leistung mit dem FirebaseUI-Recycler-Adapter, der addSnapshotListener verwendet.
Jeff Padgett
Gibt es dieses "Kaltstart" -Problem noch? Ich bin ein bisschen verwirrt über Ihr Update vom März, in dem erwähnt wird, dass die Firebase-Ingenieure wissen, was sie als "Kaltstart" -Problem kennzeichnen, weil Sie in Ihrer ursprünglichen Antwort geschrieben haben, dass Sie "4. Firestore-Kaltstart" ausgeschlossen haben das Problem?
Trollkotze
Ich sehe immer noch die langsame Leistung in Android und viele Speicherprobleme.
Plant ihr
Das Problem tritt immer noch bei der neuesten Version von firestore i auf. iOS und die Verwendung des Snapshot-Listeners funktionierten wie ein Zauber. Tolle Entdeckung.
Johndoe
8

Ich hatte dieses Problem bis heute Morgen. Meine Firestore-Abfrage über iOS / Swift würde ungefähr 20 Sekunden dauern, um eine einfache, vollständig indizierte Abfrage mit nicht proportionalen Abfragezeiten für 1 zurückgegebenes Element bis zu 3.000 abzuschließen.

Meine Lösung bestand darin, die Persistenz von Offline-Daten zu deaktivieren. In meinem Fall entsprach es nicht den Anforderungen unserer Firestore-Datenbank, in der täglich große Teile der Daten aktualisiert werden.

iOS- und Android-Benutzer haben diese Option standardmäßig aktiviert, während Webbenutzer sie standardmäßig deaktiviert haben. Es lässt Firestore wahnsinnig langsam erscheinen, wenn Sie eine riesige Sammlung von Dokumenten abfragen. Grundsätzlich wird eine Kopie der Daten zwischengespeichert, die Sie abfragen (und der Sammlung, die Sie abfragen - ich glaube, es werden alle darin enthaltenen Dokumente zwischengespeichert), was zu einer hohen Speichernutzung führen kann.

In meinem Fall verursachte es eine große Wartezeit für jede Abfrage, bis das Gerät die erforderlichen Daten zwischengespeichert hatte - daher die nicht proportionalen Abfragezeiten für die zunehmende Anzahl von Elementen, die aus genau derselben Sammlung zurückgegeben wurden. Dies liegt daran, dass das Zwischenspeichern der Sammlung in jeder Abfrage dieselbe Zeit in Anspruch nahm.

Offline-Daten - aus den Cloud Firestore-Dokumenten

Ich habe ein Benchmarking durchgeführt, um diesen Effekt (mit aktivierter Offline-Persistenz) aus derselben abgefragten Sammlung anzuzeigen, jedoch mit unterschiedlichen Mengen an Elementen, die mit dem Parameter .limit zurückgegeben wurden:

Benchmarks Bei 100 zurückgegebenen Elementen (mit deaktivierter Offline-Persistenz) dauert meine Abfrage weniger als 1 Sekunde.

Mein Firestore-Abfragecode ist unten:

let db = Firestore.firestore()
self.date = Date()
let ref = db.collection("collection").whereField("Int", isEqualTo: SomeInt).order(by: "AnotherInt", descending: true).limit(to: 100)
ref.getDocuments() { (querySnapshot, err) in
    if let err = err {
        print("Error getting documents: \(err)")
    } else {
        for document in querySnapshot!.documents {
            let data = document.data()
            //Do things
        }
        print("QUERY DONE")
        let currentTime = Date()
        let components = Calendar.current.dateComponents([.second], from: self.date, to: currentTime)
        let seconds = components.second!
        print("Elapsed time for Firestore query -> \(seconds)s")
        // Benchmark result
    }
}
Hendies
quelle
Sind diese Testnummern aus dem Web, iOS oder Android?
Sam Stern
Der Benchmark stammt von iOS, obwohl ich Leistungssteigerungen auf allen Plattformen erwarten würde - abhängig von der Größe Ihrer abgefragten Sammlung
Hendies
Ich wusste nicht, dass du im Firebase-Team bist! Das Werbegeschenk für diese Abfrage war, dass die Speichernutzung auf hohe Zahlen (600-700 MB RAM) hochgehen würde, wobei ich davon ausging, dass unsere Sammlung im Cache gespeichert war. Die Abfrage blieb immer hängen und wurde dann abgeschlossen, sobald der Speicher progressiv anstieg und dann denselben Punkt erreichte (700 MB). Nachdem die Persistenz deaktiviert wurde, hörte dieser Effekt auf und unser Gedächtnis blieb wie erwartet (100-150 MB), während unsere Ergebnisse superschnell zurückgegeben wurden. Wenn Sie weitere Informationen benötigen, fragen Sie bitte.
Hendies
Huh das ist sehr interessant. Könnten Sie möglicherweise ein Xcode-Beispielprojekt erstellen, das dies repliziert, und es mir per E-Mail senden? Wenn ja, ist es Samstern bei Google Dot Com. Ich würde gerne genauer hinsehen.
Sam Stern
@SamStern: Das ist schon eine Weile her, aber ich habe genau das gleiche Problem mit Android. Irgendwelche Hinweise darauf, was dies verursachen könnte? Ich habe versucht, ein minimales Projekt zu erstellen, aber dieses Projekt hat dieses Problem nicht!
Rednuht
6

Fast 3 Jahre später ist der Firestore noch nicht in der Beta-Phase und ich kann bestätigen, dass dieses schreckliche Problem weiterhin besteht ;-(

In unserer mobilen App verwenden wir den Firebase-Client javascript / node.js. Nach vielen Tests, um herauszufinden, warum die Startzeit unserer App etwa 10 Sekunden beträgt, haben wir herausgefunden, was 70% dieser Zeit auf ... Nun, auf die Leistung von Firebase und Firestore sowie auf Kaltstartprobleme zurückzuführen ist:

  • firebase.auth (). onAuthStateChanged () feuert ca. nach 1,5 - 2sec schon ziemlich schlecht.
  • Wenn ein Benutzer zurückgegeben wird, verwenden wir seine ID, um das Benutzerdokument aus dem Firestore abzurufen. Dies ist der erste Aufruf von firestore und das entsprechende get () dauert 4 - 5 Sekunden. Das anschließende Erhalten () derselben oder anderer Dokumente dauert ca. 500ms.

Insgesamt dauert die Benutzerinitialisierung also 6 bis 7 Sekunden, was völlig inakzeptabel ist. Und wir können nichts dagegen tun. Wir können das Deaktivieren der Persistenz nicht testen, da es im Javascript-Client keine solche Option gibt. Die Persistenz ist standardmäßig immer aktiviert, sodass durch das Nichtaufrufen von enablePersistence () nichts geändert wird.

JPJ
quelle
Gibt es eine Problemumgehung für dieses Problem? Einige Hinweise, wo nach Antworten gesucht werden kann, sind sehr willkommen.
Björnl
In der JavaScript - Client wird standardmäßig deaktiviert: For the web, offline persistence is disabled by default. To enable persistence, call the enablePersistence methodaber ich kann bestätigen , wenn das Ganze abzurunden, unsere anfängliche Anforderung mal von einer ähnlichen ~ 8 Sekunden gehen lassen bis auf etwa ~ 500ms firebase.google.com/docs/firestore/manage-data/ enable-offline
pat
Richtig, in Javascript ist es standardmäßig deaktiviert, und die oben genannten Zeiten sind mit der Standardeinstellung. In unserem Fall benötigen wir frische und aktualisierte Benutzerprofildaten, sodass die Verwendung der Persistenz keine Option ist.
JPJ
1

Nun, von dem, was ich derzeit mache und recherchiere, indem ich das Nexus 5X im Emulator und im echten Android-Handy Huawei P8 verwende.

Firestore und Cloud Storage bereiten mir beim ersten Dokument.get () und beim ersten storage.getDownloadUrl () Kopfschmerzen bei langsamer Reaktion.

Es gibt mir mehr als 60 Sekunden Antwort auf jede Anfrage. Die langsame Reaktion tritt nur bei echten Android-Handys auf. Nicht im Emulator. Eine andere seltsame Sache. Nach der ersten Begegnung ist die Restanforderung reibungslos.

Hier ist der einfache Code, in dem ich auf die langsame Antwort treffe.

var dbuserref = dbFireStore.collection('user').where('email','==',email);
const querySnapshot = await dbuserref.get();

var url = await defaultStorage.ref(document.data().image_path).getDownloadURL();

Ich habe auch einen Link gefunden, der das gleiche erforscht. https://reformatcode.com/code/android/firestore-document-get-performance

Kyo Kurosagi
quelle