Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent slow INNER JOIN in Django model calls when unnecessary

Is it possible to prevent Django from using INNER JOIN in SQL relationship queries when unnecessary?

I have the two tables:

class Author(models.Model):
    name = models.CharField(max_length=50, primary_key=True, db_index=True)
    hometown = models.CharField(max_length=50)

class Book(models.Model):
    title = models.CharField(max_length=50, primary_key=True, db_index=True)
    author = models.ForeignKey(Author, db_index=True)

The author table has more than 50 million rows, which makes requests such getting all the books of one author, Book.objects.filter(author_id='John Smith'), incredibly slow (about 20 sec). However, when I use raw SQL to achieve the same result, the query is almost instant: SELECT * FROM books WHERE author_id='John Smith';.

Using result.query I have found that Django is slower because it runs a INNER JOIN query on the entire table:

SELECT books.title, books.author_id FROM books INNER JOIN authors 
    ON (books.author_id = authors.name) WHERE books.author_id = 'John Smith';

Is there a way to make Django avoid the INNER JOIN in cases such as this when it isn't necessary?

I would like to avoid using raw SQL queries if at all possible as this database structure is highly simplified.

like image 903
dwitvliet Avatar asked Sep 03 '25 16:09

dwitvliet


1 Answers

The solution turned out to be removing a class Meta option:

class Book(models.Model):

    (...)

    class Meta:
        ordering = ['author', 'title']
like image 173
dwitvliet Avatar answered Sep 05 '25 08:09

dwitvliet