Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I avoid multi-table (concrete) inheritance in Django by any means?

Many experienced developers recommend against using Django multi-table inheritance because of its poor performance:

  1. Django gotcha: concrete inheritance by Jacob Kaplan-Moss, a core contributor of Django.

    In nearly every case, abstract inheritance is a better approach for the long term. I’ve seen more than few sites crushed under the load introduced by concrete inheritance, so I’d strongly suggest that Django users approach any use of concrete inheritance with a large dose of skepticism.

  2. Two Scoops of Django by Daniel Greenfield (@pydanny)

    Multi-table inheritance, sometimes called “concrete inheritance,” is considered by the authors and many other developers to be a bad thing. We strongly recommend against using it.

    At all costs, everyone should avoid multi-table inheritance since it adds both confusion and substantial overhead. Instead of multi-table inheritance, use explicit OneToOneFields and ForeignKeys between models so you can control when joins are traversed.

But without multi-table inheritance, I can't easily

  1. Reference base model in another model (have to use GenericForeignKey or reverse dependency);

  2. Get all instances of base model.

    (feel free to add more)

So what is wrong with this kind of inheritance in Django? Why are explicit OneToOneFields better?

How much does performance suffer from JOINs? Are there any benchmarks that show the difference in performance?

Does not select_related() allow us to control when JOINs are invoked?


I have moved concrete examples to a separate question since this one is becoming too broad, and added a list of reasons for using multi-table inheritance instead.

like image 203
utapyngo Avatar asked May 05 '14 06:05

utapyngo


People also ask

What is multi-table inheritance Django?

In multi-table inheritance, each model corresponds to a database table. Django creates a OneToOneField field for the relationship in the child's model to its parent. To use multi-table inheritance, you have to subclass an existing model. Django will create a database table for both the original model and the sub-model.

Which below option is the inheritance style in Django?

Proxy Model Inheritance: You Inherit from base class and you can add your own properties except fields.

How many types of inheritance are there in Django?

There are three styles of inheritance that are possible in Django. Often, you will just want to use the parent class to hold information that you don't want to have to type out for each child model.

What is your understanding of Django model inheritance?

Models inheritance works the same way as normal Python class inheritance works, the only difference is, whether we want the parent models to have their own table in the database or not. When the parent model tables are not created as tables it just acts as a container for common fields and methods.


1 Answers

First of all, inheritance has not a natural translation to relational database architecture (ok, I know, Oracle Type Objects and some other RDBMS support inheritance but django don't take advantage of this functionality)

At this point, notice than django generates new tables to subclasses and write lots of left joins to retrieve data from this 'sub-tables'. And left joins are not your friends. In a high performance scenario, like a game backend or something else, you should avoid it and resolve inheritance 'by hand' with some artifacts like nulls, OneToOne or foreign keys. In OneToOne scenario, you can call the related table directly or only if you need it.

... BUT ...

"In my opinion (TGW)" you should to include model inheritance in your enterprise projects when it catches to your universe of discourse. I do this, and I save a lot of development hours to my customers thanks to this feature. Also, code becomes clean and elegant and that means easy maintenance (notice that this kind of projects don't have hundreds or requests by second)

Question by question

Q: What is wrong with this kind of inheritance in Django?
A: Lot of tables, a lot of left joins.

Q: Why are explicit OneToOneFields better?
A: You can access directly to related model without left joins.

Q: Are there any illustrative examples (benchmarks)?
A: No comparable.

Q: Does not select_related() allow us to control when JOINs are invoked?
A: django joins needed tables.

Q: What are the alternatives to multi-table inheritance when I need to reference a base class in another model?
A: Nullification. OneToOne relations and lots of code lines. It depends on application needs.

Q: Are GenericForeignKeys better in this case?
A: Not for me.

Q: What if I need OneToOneField to base model?
A: Write it. There is no problem with this. For example, you can extend User model, and also you can have a OneToOne to User base model for some users.

Conclusion

You should to know the cost of write and maintenance code without model inheritance also the cost of hardware to support model inheritance applications and act accordingly.

Just a joke: you can write it on assembly code, and it will run faster.

Quoting Trey Hunner:

Your time is usually much more expensive than your CPU's time.

like image 99
dani herrera Avatar answered Nov 04 '22 18:11

dani herrera