DGDD
DGDD

Reputation: 1390

Performance difference between calling values from model and foreign model

How much of a performance difference is there between these two type of queries?

Say I have these 3 models:

class Brand(models.Model):
    brand_name = models.CharField()

class Model(models.Model):
    brand = Models.ForeignKey(Brand)
    model_name = models.CharField()

class Listing(models.Model):
    model = Models.ForeignKey(Model)
    listing_info = models.CharField()

I have several thousand listings that I am showing in the templates and I would like to display the brand_name and model_name for each listing.

In the templates I list this as such:

<p>{{ listing.model.brand.brand_name }}</p>
<p>{{ listing.model.model_name }}</p>
<p>{{ listing.listing_info }}</p>

Now consider if I listed those values right in the Listing model (duplicate the data):

class Listing(models.Model):
    model = Models.ForeignKey(Model)
    brand_name = models.CharField()
    model_name = models.CharField()
    listing_info = models.CharField()

Then in the templates I could simply list as such:

<p>{{ listing.brand_name }}</p>
<p>{{ listing.model_name }}</p>
<p>{{ listing.listing_info }}</p>

Thinking beyond the problem of having data duplication, how much of a performance difference is there between the two setups?

Upvotes: 0

Views: 31

Answers (1)

Alasdair
Alasdair

Reputation: 308769

If you use select_related, then Django will fetch the related model and brand data at the same time as it fetches the listings.

Listing.objects.filter().select_related('model', 'model__brand')

As an example, say you have 100 listings. Without select_related, there would be 201 queries (1 query to fetch all the listings, 100 to fetch each listing's model and 100 to fetch each model's brand). With select_related, everything is fetched in 1 query.

In theory, denormalizing the data (duplicating attributes in the Listing model) might offer a further performance benefit, but the improvement would probably be negligible. You would have to measure it to see. Most of the time, using select_related is good enough.

Upvotes: 4

Related Questions