2009-12-30 6 views
1

J'ai trois modèles: Produit, Catégorie et Lieu. Le produit a beaucoup de relations avec la catégorie et le lieu. Je dois obtenir une liste de catégories avec au moins un produit correspondant à un lieu spécifique. Par exemple, je pourrais avoir besoin de toutes les catégories qui ont au moins un produit de Boston.est distincte une requête coûteuse en django?

J'ai 100 catégories, 500 places et 100 000 produits.

En sqlite avec des produits 10K, la requête prend ~ une seconde. En production, je vais utiliser postgresql.

J'utilise:

categories = Category.objects.distinct().filter(product__place__name="Boston") 

Est-ce cette requête va être cher? Y a-t-il une meilleure façon de faire cela?

Ceci est le résultat de connection.queries

{'time': '0.929', 'sql': u'SELECT DISTINCT "catalog_category"."id", "catalog_category"."name" FROM "catalog_category" INNER JOIN "catalog_product_categories" ON ("catalog_category"."id" = "catalog_product_categories"."category_id") INNER JOIN "catalog_product" ON ("catalog_product_categories"."product_id" = "catalog_product"."id") INNER JOIN "catalog_product_places" ON ("catalog_product"."id" = "catalog_product_places"."product_id") INNER JOIN "catalog_place" ON ("catalog_product_places"."car_id" = "catalog_car"."id") WHERE "catalog_place"."name" = Boston ORDER BY "catalog_category"."name" ASC'}] 

Merci

Répondre

0

Ce n'est pas seulement une question de Django; DISTINCT est lent sur la plupart des implémentations SQL car il s'agit d'une opération relativement difficile. Here est une bonne discussion pour savoir pourquoi il est lent dans Postgres en particulier. Une façon de gérer cela serait d'utiliser l'excellent caching mechanism de Django sur cette requête, en supposant que les résultats ne changent pas souvent et que l'obsolescence mineure n'est pas un problème. Une autre approche consisterait à conserver une liste séparée des catégories distinctes, peut-être dans un autre tableau.

+1

Le lien vers le mécanisme de mise en cache de Django est cassé, mais l'ajout d'un seul caractère est une modification trop petite. Il ne manque qu'un "e" final Il devrait être: http://docs.djangoproject.com/fr/dev/topics/cache – andrewsomething

-1

Bien que Chase a raison de dire que DISTINCT est généralement une opération lente, dans ce cas, il est également complètement inutile. Comme vous pouvez le voir à partir du SQL généré, le DISTINCT est fait sur la combinaison de l'ID et du nom - qui ne sera jamais dupliqué de toute façon. Il n'y a donc pas besoin de l'appel distinct() dans cette requête.

Généralement, Django ne renvoie pas les résultats en double d'un simple filtre. L'heure principale où distinct() est utile est lorsque vous accédez à un ensemble de requêtes associé via une relation ManyToMany ou ForeignKey, où plusieurs éléments peuvent être associés à la même instance, et distinct supprime les doublons.

+2

Je reçois des résultats en double dans ce cas si je n'utilise pas distinct() et je fais avoir une relation ManyToMany. À moins que je manque quelque chose et que je fasse quelque chose de mal? – pablo

Questions connexes