16

Sorry, wenn diese Frage zu einfach ist; Ich gehe erst in die 9. Klasse.Effiziente Eins-zu-viele-Beziehungen im Google App Engine-Datenspeicher?

Ich versuche, über NoSQL-Datenbank-Design zu lernen. Ich möchte ein Google Datastore-Modell entwerfen, das die Anzahl der Lese-/Schreibvorgänge minimiert.

Hier ist ein Spielzeugbeispiel für einen Blogpost und Kommentare in einer Eins-zu-viele-Beziehung. Was ist effizienter - alle Kommentare in einer StructuredProperty speichern oder eine KeyProperty im Comment-Modell verwenden?

Das Ziel besteht wiederum darin, die Anzahl der Lese-/Schreibvorgänge im Datenspeicher zu minimieren. Sie können folgende Annahmen treffen:

  • Kommentare werden nicht unabhängig von ihrem jeweiligen Blogpost abgerufen. (Ich vermute, dass dies macht den StructuredProperty am meisten bevorzugt.)
  • Kommentare benötigen nach Datum sortierbar sein, Bewertung, Autor usw. (Subproperties im Datenspeicher können nicht indiziert werden, so vielleicht könnte dies die Leistung beeinträchtigen?)
  • Sowohl Blogposts als auch Kommentare können nach ihrer Erstellung bearbeitet (oder sogar gelöscht) werden.

Mit StructuredProperty:

from google.appengine.ext import ndb 

class Comment(ndb.Model): 
    various properties... 

class BlogPost(ndb.Model): 
    comments = ndb.StructuredProperty(Comment, repeated=True) 
    various other properties... 

Mit KeyProperty:

from google.appengine.ext import ndb 

class BlogPost(ndb.Model): 
    various properties... 

class Comment(ndb.Model): 
    blogPost = ndb.KeyProperty(kind=BlogPost) 
    various other properties... 

Fühlen Sie sich frei weitere Überlegungen zu bringen, die effizient beziehen sich auf die eine Eins-zu-viele-Beziehung in Bezug auf die Minimierung die Anzahl der Lese-/Schreibvorgänge im Datenspeicher.

Danke.

+0

Überlegen Sie, wie Sie das Problem der Gesamtgröße von Kommentaren und Blogpost größer als 1 MB lösen würden. Kann es jemals passieren? Wenn es möglich ist und Sie keine gute Lösung dafür haben, dann scheint es aus rein funktionaler Sicht, dass Sie sich nicht einmal mit einer einzelnen Entität befassen würden, die beides enthält. –

+0

Eine Alternative könnte sein, einfach alle Schlüssel der Kommentare im Blogpost zu speichern. Dann können Sie alle Kommentare mit einem einzelnen ndb.get_multi (Schlüssel) abrufen, aber würden wesentlich mehr Kommentare erlauben, und wenn Sie immer noch über 1MB gehen, dann können Sie einzelne Kommentare abrufen –

Antwort

13

Ich könnte falsch liegen, aber von was ich verstehe, ist eine StructuredProperty nur eine Eigenschaft innerhalb einer Entität, aber mit Untereigenschaften.

Dies bedeutet, ein BlogPost lesen und alle seine Kommentare würden nur einen gelesen werden. Wenn Sie also Ihre Seite rendern, benötigen Sie nur eine Leseoperation für Ihre gesamte Seite.

Schreiben wäre auch billiger. Sie benötigen eine Leseoperation, um den BlogPost zu erhalten, und solange Sie keine indexierten Eigenschaften aktualisieren, ist es nur ein Schreibvorgang.

Sie können die Sortierung der Kommentare selbst durchführen, nachdem Sie die Entität aus dem Datenspeicher gelesen haben.

Sie müssen Ihre Kommentaraktualisierungen/-änderungen mit Transaktionen synchronisieren, um sicherzustellen, dass ein Kommentar keinen anderen überschreibt, da beide dieselbe Entität ändern. Es kann zu unlösbaren Problemen kommen, wenn alle denselben Blog-Post gleichzeitig kommentieren und bearbeiten.

Wenn Sie jedoch die Kosten optimieren, treffen Sie eine Wand mit der maximalen Größe von 1 MB. Dadurch wird die Anzahl der Kommentare begrenzt, die Sie pro Blogpost speichern können.

Mit der KeyProperty zu gehen wäre ein bisschen teurer.

Sie benötigen einen Lesezugriff, um den Blogpost zu erhalten, plus eine Abfrage plus 1 kleiner Lesezugriff für jeden Kommentar.

Jeder Kommentar ist eine neue Entität, also sind es mindestens 4 Schreiboperationen. Möglicherweise möchten Sie für die Sortierreihenfolge indizieren, so dass es am Ende noch mehr Schreiboperationen kostet.

Auf der positiven Seite haben Sie unbegrenzte Kommentare pro Blogpost, Sie müssen sich keine Gedanken über die Synchronisierung neuer Kommentare machen. Möglicherweise müssen Sie sich über die Synchronisierung für die Bearbeitung von Kommentaren Gedanken machen, aber wenn Sie die Bearbeitung auf den Ersteller beschränken, sollte das eigentlich kein Problem sein. Sie müssen sich auch nicht selbst sortieren.

Es ist eine Kosten vs Funktionen Kompromiss.

3

Was:

from google.appengine.ext import ndb 

class Comment(ndb.Model): 
    various properties... 

class BlogPost(ndb.Model): 
    comments = ndb.KeyProperty(Comment, repeated=True) 
    various other properties... 

Auf diese Weise können Sie bis 5000 Kommentare per Blogeintrag speichern (die maximale Anzahl der wiederholten Eigenschaften) unabhängig von der Größe der einzelnen Blog-Post. Sie brauchen keine Abfrage, um die Blogs für einen Kommentar zu holen, Sie können einfach ndb.get_multi(blog_post.comments) tun. Und für diese Operation können Sie versuchen, sich auf das Memcache von ndb zu verlassen. Es hängt natürlich von Ihrem Anwendungsfall ab, ob dies eine gute Annahme ist oder nicht.

1

Schreiben dieser Einschränkung bewusst, wenn eine wiederholte StructuredProperty mit:

Verwenden Sie wiederholte Eigenschaften nicht, wenn Sie mehr als 100-1000 Werte haben. (1000 ist wahrscheinlich schon drängen.) Sie waren nicht für eine solche Verwendung konzipiert.

Siehe Guidos Antwort in GAE ndb design, performance and use of repeated properties.

Obwohl Sie das 1-MB-Entity-Limit mit StructuredProperty nicht erreichen können, können Sie leicht den 100-1000-Maximalwert erreichen.

+0

So was ist die Alternative? Just KeyProperty, wie in der Frage? Oder gibt es einen besseren Weg? – Ajedi32

+0

Eine KeyProperty könnte funktionieren, wenn sie unter dem Wert von 100-1000 liegt, aber wenn Sie mehr haben, würde ich überdenken, Ihr Datenmodell und benötigte Features zu überdenken. Im Fall des Blog-Beispiels könnte das Speichern der Kommentare als einzelne JSONProperty ebenfalls funktionieren. Auf diese Weise aktualisieren/lesen Sie nur 1 Entity (den BlogPost) und aktualisieren ihre JSONProperty für die Kommentare. Dies ist vergleichbar mit der StructuredProperty-Lösung ohne die Beschränkung auf 100-1000 Werte. Natürlich, wenn die Entity größer als 1 MB wird, wird dies nicht funktionieren (es sei denn, Sie teilen es in mehrere Entitäten ...), aber das könnte für Ihren Anwendungsfall funktionieren. –