2010-06-04 7 views
6

Les deux types de données possibles sont les suivants: Text et Blob.Banque de données Google - Blob ou texte

Du point de vue de la consommation de stockage, lequel des 2 est recommandé? Même question à partir d'une perspective de sérialisation et de désérialisation de protobuff.

Répondre

4

Il n'y a pas de différence de performance significative entre les deux - il suffit d'utiliser celui qui correspond le mieux à vos données. BlobProperty doit être utilisé pour stocker des données binaires (par exemple, des objets str) tandis que TextProperty doit être utilisé pour stocker des données textuelles (par exemple, unicode ou str objets). Notez que si vous stockez un str dans un TextProperty, il doit contenir uniquement des octets ASCII (moins de hexadécimal 80 ou décimal 128) (contrairement à BlobProperty).

Ces deux propriétés sont dérivées de UnindexedProperty comme vous pouvez le voir dans le source.

Voici une application exemple qui démontre qu'il n'y a pas de différence dans les frais généraux de stockage pour ces ASCII ou UTF-8 chaînes:

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() 

Et voici la sortie:

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

Je n » étais pas t conscient que les propriétés de texte ne peuvent contenir que des octets ASCII. Cette réalisation répond à ma question. Merci. – Keyur

+1

Ce n'est pas vrai - les propriétés de texte stockent unicode. Mais si vous affectez une chaîne octet ('raw') (type 'str') à une propriété text, elle tentera de convertir en unicode, qui utilise le codage par défaut du système, qui est ASCII. Vous devez décoder les chaînes explicitement si vous voulez faire autrement. –

+0

Merci Nick. J'essayais de dire que 'TextProperty' ne peut pas stocker les objets' str' qui contiennent des octets non-ASCII mais (comme vous l'avez souligné) mon commentaire ne l'a pas rendu clair donc je l'ai supprimé. –

Questions connexes