2016-04-19 8 views
2

In einer Python GAE-Anwendung, an der ich arbeite, müssen wir n Zeilen aus dem Speicher abrufen, und wir stoßen auf Leistungsprobleme für n> 100. Wir erwarten, dass n in den meisten Fällen weniger als 10000 ist.Wie schnell eine Anzahl von Zeilen aus dem Datenspeicher abrufen?

Also lassen Sie uns ein einfaches Modell betrachten:

class MyEntity(ndb.Model): 
    field1 = nbd.StringProperty() 
    field2 = ndb.StringProperty() 
    #... 
    fieldm = ndb.StringProperty() 
    # m is quite large, maybe ~ 30. Stored strings are short - in the order of 30 characters or less 

Ich habe den Datenspeicher mit einigen Daten gefüllt, und bekam wirklich schlechte Leistung Ebene fetch() verwenden. Ich habe seither alle Filter entfernt und nur versucht, eine Anzahl von Entitäten zu bekommen, scheint sehr schlechte Leistung zu bekommen (im Vergleich zu dem, was ich zum Beispiel für jede gebräuchliche SQL-Implementierung erwarte. Ich weiß, dass wir GAE nicht vergleichen sollten SQL, aber nur flache Zeilen runter - ich würde erwarten, mehr Leistung zu sein, nicht weniger). Hier ist, was ich versucht habe:

  • Der einfachste Ansatz MyEntity.all().fetch(n). Dies skaliert linear mit n, was erwartet wird. Obwohl ich nicht erwartet habe, dass es 7s für n = 1000 dauert.
  • Der Versuch, fetch() mit jedem vernünftigen batch_size zu zwingen, verschlechtert die Leistung weiter. Ich habe versucht Werte von 1 bis 1000.
  • Doing gibt eine Größenordnung Verbesserung.
  • Eine Abfrage manuell durchführen (through ndb.Query), und nur ein einzelnes Feld herausgeben gibt eine kleine Verbesserung in der Größenordnung von 1,2.
  • Doing a fetch_async(n) und warten gibt genau die gleiche Leistung.
  • Teilen Sie den Job in Teile, dann tun fetch_async(n/p, offset=...) und dann warten und Beitritt alle Futures - gibt bestenfalls die gleiche Leistung, im schlimmsten Fall - viel schlechtere Leistung.
  • ähnliche Geschichte mit fetch_page()

hat ich versucht, auch db statt ndb verwenden, und die Ergebnisse sind so ziemlich das gleiche. Also, jetzt bin ich mir nicht sicher, was ich tun soll? Gibt es eine Möglichkeit, eine halbwegs ordentliche Leistung für n in der Größenordnung von 10000 zu bekommen? Selbst wenn ich meine Entitäten zu einzelnen Feldern vereinfache, ist die Leistung zu schlecht. Ich erwarte, dass die gesamte unkomprimierte Nutzlast ungefähr 1 MB beträgt. Das Herunterladen von 1 MB innerhalb einer Minute ist eindeutig inakzeptabel.

Ich sehe dieses Problem live, aber für Leistungstests verwende ich Remote-API. Meine Frage ähnelt dieser Frage zu SO: Best practice to query large number of ndb entities from datastore. Sie schienen keine Lösung zu finden, aber sie wurde vor 4 Jahren gefragt, vielleicht gibt es jetzt eine.

+0

Was sehen Sie in den Protokollen für diese Anfrage? –

+0

Was möchten Sie tun, nachdem Sie die Zeilen abgerufen haben? – Vincent

Antwort

1

Wenn Sie nur eine Teilmenge der Felder für das Modell benötigen, dann schauen Sie in Projection Queries

+0

Es gibt einen Leistungsvorteil beim Erhalten einer Menge von Abfragen, aber ich suche nach einer allgemeinen Lösung, die die Leistung erhöhen würde, n ~ 10000 Zeilen zu erhalten. – Gleno

1

können Sie eine bessere Leistung je nachdem, was Sie mit den abgerufenen Daten tun müssen. Zum Beispiel, wie Sie _asyncdocumentation here verwenden. Sie können eine Teilmenge der Daten abrufen, z. B. zuerst 100, und dann _async für die nächste Teilmenge von 100 Datensätzen aufrufen, während der erste Datenstapel verarbeitet wird, da _async nicht blockiert ist. Am Ende Ihrer Bearbeitung verwenden Sie .get_result(), um die Ergebnisse der zweiten Charge abzurufen und mit der Verarbeitung der Daten zu beginnen, während die dritte Charge mit _async ... usw. aufgerufen wird.

Verwandte Themen