2011-03-24 2 views
11

J'ai visité http://guides.rubyonrails.org/active_record_querying.html après avoir discuté avec un homologue concernant N + 1 et les implications sérieuses des performances des requêtes DB incorrectes.Solution de requête Django N + 1

ActiveRecord (Rails):

clients = Client.includes(:address).limit(10) 

où les adresses du client ont, et je compte y accéder en boucle à travers les clients, Rails fournit includes pour le faire savoir aller de l'avant et les ajouter à la requête, ce qui élimine 9 requêtes dès le départ.

Django:

https://github.com/lilspikey/django-batch-select fournit un support de requête par lot. Connaissez-vous d'autres bibliothèques ou astuces pour réaliser ce que Rails fournit ci-dessus, mais dans un manoir moins verbeux (comme dans l'exemple des rails où seulement 19 caractères fixent N + 1 et est très clair)? En outre, est-ce que la sélection par lots traite le problème de la même manière, ou s'agit-il de deux choses différentes?

BTW, je ne parle pas de select_related, même si cela peut sembler être la réponse à première vue. Je parle d'une situation où address a une clé forign à client.

Répondre

9

Malheureusement, l'ORM de Django n'a pour l'instant aucun moyen de le faire.

Heureusement, il est possible de le faire en seulement 2 requêtes, avec un peu de travail en Python.

clients = list(Client.objects.all()[:10]) 
addresses = dict((x.client_id, x) for x in 
    Address.objects.filter(client__in=clients)) 
for client in clients: 
    print client, addresses[client.id] 
+0

merci. BTW, cela créera-t-il une requête aussi efficace (c.-à-d. Est-ce que Rails est susceptible de faire quelque chose de magique qui fournit de meilleures performances, ou est-ce probablement du sucre syntaxique pour la même chose)? Évidemment, ce serait mieux si tout ne devait pas être évalué immédiatement, mais peut-être que le leur aussi. – orokusaki

+0

Je ne sais pas. Il est * possible * d'effectuer l'action dans une requête, mais cela nécessite un niveau de supercherie que l'ORM de Django n'a pas encore. –

+0

ok. Merci encore. – orokusaki

2

django-batch-select est censé fournir une réponse à ce problème, mais je ne l'ai pas essayé. La réponse d'Ignacio ci-dessus me semble la meilleure.