2010-06-04 5 views
6

2 Möglichkeiten, große Strings im Google Datastore zu speichern, sind Text und Blob Datentypen.Google Datastore - Blob oder Text

Aus Speicherperspektive, welche der 2 wird empfohlen? Die gleiche Frage stammt von einer protobuf-Serialisierungs- und Deserialisierungsperspektive.

Antwort

4

Es gibt keine wesentlichen Leistungsunterschiede zwischen den beiden - verwenden Sie einfach den, der am besten zu Ihren Daten passt. BlobProperty sollte verwendet werden, um Binärdaten (z. B. str-Objekte) zu speichern, während TextProperty verwendet werden sollte, um beliebige Textdaten zu speichern (z. B. unicode oder str Objekte). Beachten Sie, dass wenn Sie eine str in einer TextProperty speichern, sie nur ASCII-Bytes (kleiner als hex 80 oder dezimal 128) enthalten muss (anders als BlobProperty).

Beide Eigenschaften sind von UnindexedProperty abgeleitet, wie Sie in der source sehen können.

Hier ist eine Beispielanwendung, die, dass es zeigt keinen Unterschied in der Speicheraufwand für diese ASCII oder UTF-8-Zeichenketten:

import struct 

from google.appengine.ext import db, webapp 
from google.appengine.ext.webapp.util import run_wsgi_app 

class TestB(db.Model): 
    v = db.BlobProperty(required=False) 

class TestT(db.Model): 
    v = db.TextProperty(required=False) 

class MainPage(webapp.RequestHandler): 
    def get(self): 
     self.response.headers['Content-Type'] = 'text/plain' 

     # try simple ASCII data and a bytestring with non-ASCII bytes 
     ascii_str = ''.join([struct.pack('>B', i) for i in xrange(128)]) 
     arbitrary_str = ''.join([struct.pack('>2B', 0xC2, 0x80+i) for i in xrange(64)]) 
     u = unicode(arbitrary_str, 'utf-8') 

     t = [TestT(v=ascii_str), TestT(v=ascii_str*1000), TestT(v=u*1000)] 
     b = [TestB(v=ascii_str), TestB(v=ascii_str*1000), TestB(v=arbitrary_str*1000)] 

     # demonstrate error cases 
     try: 
      err = TestT(v=arbitrary_str) 
      assert False, "should have caused an error: can't store non-ascii bytes in a Text" 
     except UnicodeDecodeError: 
      pass 
     try: 
      err = TestB(v=u) 
      assert False, "should have caused an error: can't store unicode in a Blob" 
     except db.BadValueError: 
      pass 

     # determine the serialized size of each model (note: no keys assigned) 
     fEncodedSz = lambda o : len(db.model_to_protobuf(o).Encode()) 
     sz_t = tuple([fEncodedSz(x) for x in t]) 
     sz_b = tuple([fEncodedSz(x) for x in b]) 

     # output the results 
     self.response.out.write("text: 1=>%dB 2=>%dB 3=>%dB\n" % sz_t) 
     self.response.out.write("blob: 1=>%dB 2=>%dB 3=>%dB\n" % sz_b) 

application = webapp.WSGIApplication([('/', MainPage)]) 
def main(): run_wsgi_app(application) 
if __name__ == '__main__': main() 

Und hier ist die Ausgabe:

text: 1=>172B 2=>128047B 3=>128047B 
blob: 1=>172B 2=>128047B 3=>128047B 
+2

I wasn‘ Beachten Sie, dass Texteigenschaften nur ASCII-Bytes enthalten können. Diese Erkenntnis beantwortet meine Frage. Vielen Dank. – Keyur

+1

Das ist nicht wahr - Texteigenschaften speichern Unicode. Wenn Sie jedoch einer Texteigenschaft eine Byte-Zeichenfolge ('raw') ('str') zuweisen, wird sie versuchen, in Unicode zu konvertieren, wobei die Standardcodierung des Systems verwendet wird, bei der es sich um ASCII handelt. Sie müssen Strings explizit dekodieren, wenn Sie etwas anderes tun möchten. –

+0

Danke Nick. Ich habe versucht zu sagen, dass 'TextProperty' keine 'str'-Objekte speichern kann, die Nicht-ASCII-Bytes enthalten, aber mein Kommentar hat das nicht klar gemacht, also habe ich es gelöscht. –