Reputation: 3698
I read here that multi-table inheritance can cause performance issues, and instead explicit OneToOneField is recommended.
Here is my situation:
class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=10)
category = models.ForeignKey('Category', on_delete=models.CASCADE, blank=False)
class Book(Product):
publisher = models.CharField(max_length=50)
author = models.CharField(max_length=50)
isbn = models.CharField(max_length=50)
class Shoes(Product):
size = models.PositiveSmallIntegerField()
colour = models.CharField(max_length=20, choices=[('black', 'Black'), ('white', 'White')])
I don't understand why would explicit OneToOneField bring performance gains, when multi-table inheritance is implemented in exactly the same way:
place_ptr = models.OneToOneField(
Place, on_delete=models.CASCADE,
parent_link=True,
)
If this is true despite everything, I would like to know how could I alter my models so they use explicit OneToOneField. So, if I create a Book instance, Product.objects.all()
should retrieve that instance of Book, too.
Upvotes: 4
Views: 1222
Reputation: 16042
I'd be a bit skeptical of the conclusion that multi-table inheritance causes performance issues for a variety reasons:
The reason using multi-table inheritance is inefficient is because it generates an extra table for the base model, and therefore extra JOINs to access those fields.
The above statement may be true, but it doesn't explain how explicit OneToOneField
s are better, which is the main premise of user193130's answer.
The real question you should ask yourself is, should I join table x and table y?, which, as turns out, is an extremely complicated question.
Here is a list of resources related to this topic, most of which support my skepticism:
a comment on dani herrera's answer:
"Q: Why are explicit OneToOneFields better? A: You can access directly to related model without left joins." this is somewhat misleading. I think you need joins anyway. The difference is whether you do it explicitly or implicitly. Please correct me if I'm wrong
to which dani herrara replies:
@eugene, you are right. Be free to improve answer. Thanks!
Using separate models (and tables) only makes sense for the purposes of modularization -- such that you subclass Project to create a specific kind of project that requires additional fields but still needs all the fields of a generic Project.
It depends on the situation. If there's a clear is-a relationship going on. Like class Dog(Animal), then you should use MTI (If it's called for. Some other form of inheritance may be more appropriate). But, in the case of something like auth.User, a UserProfile is not really a type of User, so OneToOneField makes more sense. However, the BIG caveat there is that UserProfile is used because User cannot be altered. Otherwise, simply adding additional fields to User would be more appropriate
Upvotes: 2