adder
adder

Reputation: 3698

Model inheritance: benefits of explicit OneToOneField vs implicit multi-table inheritance OneToOneField

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

Answers (1)

Lord Elrond
Lord Elrond

Reputation: 16042

I'd be a bit skeptical of the conclusion that multi-table inheritance causes performance issues for a variety reasons:

  • That question is 5 years old, so the answers might be outdated.
  • this answer contradicts that conclusion
  • The only explanations given for why model inheritance is bad are that it requires LEFT JOINs or

    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 OneToOneFields 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!

  • The last lines of Chris Pratt's answer:

    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.

  • Comment in Chris Pratt's other answer:

    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

Related Questions