0

Le mois dernier, j'ai eu un petit problème avec une requête de base de données assez basique. Il s'agit de 2 db.Models dont l'un se réfère à l'autre avec une propriété db.ReferenceProperty.Performances du datastore, mon code ou la latence du datastore

Le problème est que, selon les journaux d'administration, la requête prend environ 2 à 4 secondes. Je le dépouille à une forme nue et une liste pour afficher les résultats. Le put fonctionne très bien, mais le get accumule (à mon avis) beaucoup de temps CPU.

#The get look like this: 
outputData['items'] = {} 
labelsData = Label.all() 
for label in labelsData: 
     labelItem = label.item.name 
     if labelItem not in outputData['items']: 
       outputData['items'][labelItem] = { 'item' : labelItem, 'labels' : [] } 
     outputData['items'][labelItem]['labels'].append(label.text) 
path = os.path.join(os.path.dirname(__file__), 'index.html') 
self.response.out.write(template.render(path, outputData)) 
#And the models: 
class Item(db.Model): 
     name = db.StringProperty() 
class Label(db.Model): 
     text = db.StringProperty() 
     lang = db.StringProperty() 
     item = db.ReferenceProperty(Item) 

J'ai essayé de faire un certain nombre de façon différente ie. au lieu de ReferenceProperty qui stocke toutes les clés Label dans le modèle d'élément en tant que db.ListProperty.

Mes données de test sont juste 10 lignes dans Item et 40 dans Label. Donc mes questions: Est-ce une course de fous pour essayer d'optimiser ceci puisque l'utilisation élevée de cpu est due aux problèmes avec la banque de données ou ai-je juste foiré quelque part dans le code? ..fredrik

EDIT:

J'eu une très bonne réponse de djidjadji à la liste de diffusion AppEngine google.

Le nouveau code ressemble à ceci:

Répondre

3

Il y a certainement des choses que vous pouvez faire pour optimiser votre code. Par exemple, vous itérez une requête, ce qui est moins efficace que de récupérer la requête et d'effectuer une itération sur les résultats.

Je vous recommande d'utiliser Appstats pour profiler votre application, et consultez la série de publications Patterns of Doom.

+0

J'ai utilisé Appstats. Et c'est le ReferenceProperty qui fait et interroge pour chaque boucle qui est le problème. Mais j'ai reçu de l'aide sur la liste de diffusion googleappengine. Je ne savais pas comment faire le même résultat sans faire référence à ReferenceProperty. La solution consistait à utiliser get_value_for_datastore avant la boucle for. – fredrik

+1

Vous avez toujours le problème d'itération sur une requête. Appeler .fetch() au lieu d'itérer sur la requête sera beaucoup plus efficace. En outre, voir ce billet de blog pour une recette pour résoudre les propriétés de référence: http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine –

0

N'essayez pas seulement des choses. C'est deviner. Vous aurez seulement raison certains de l'époque. Ne demandez pas aux autres de deviner non plus, pour la même raison.

Sois correct à chaque fois. Il suffit de mettre le code plusieurs fois en pause et de regarder la pile d'appels. Cela vous dira exactement ce qui se passe.

+0

Malheureusement on finit par deviner quand sa connaissance ne couvre pas la question à portée de main. Cela devient encore plus difficile quand on ne connait pas plus d'informations spécifiques à ce sujet alors "ça court à beaucoup de requêtes". La solution que j'ai eu pour la liste de diffusion de google appengine était quelque chose que je ne savais pas qu'il était possible de faire. J'ai lu à ce sujet dans la documentation, mais je n'ai pas compris ce qu'il a fait. Donc, si vous dites qu'il ne faut pas deviner, comment vous y prendrez-vous? – fredrik

+0

@fredrik: Voici ce que je suggère. Exécutez votre programme sous le pdb (http://docs.python.org/library/pdb.html). Appuyez sur Ctrl-Break ou Ctrl-C pendant son exécution. Tapez "w (ici)" pour voir la pile d'appels. Comprendre ce qu'il fait et pourquoi. Répétez plusieurs fois.Si X% est passé dans votre code, X% (+/-) piles l'affichera. Si dans le magasin de données, même chose. La mesure sera approximative, mais l'activité sera certaine et détaillée. C'est ce que je veux dire en ne devinant pas. –