43

It seems like it should be easy to run "explain" directly off of a queryset in Django, but I don't see anything obvious for how to do it, and "explain" is a difficult thing to search for in the docs.

Makoto
  • 104,088
  • 27
  • 192
  • 230
guidoism
  • 7,820
  • 8
  • 41
  • 59

3 Answers3

38

Well, there seems to be nothing out there except a toolbar so I wrote my own mixin to give me an explain() method on my querysets:

from django.db import connections
from django.db.models.query import QuerySet

class QuerySetExplainMixin:
    def explain(self):
        cursor = connections[self.db].cursor()
        cursor.execute('explain %s' % str(self.query))
        return cursor.fetchall()

QuerySet.__bases__ += (QuerySetExplainMixin,)

Hopefully this is useful to others.

Tzach
  • 12,889
  • 11
  • 68
  • 115
guidoism
  • 7,820
  • 8
  • 41
  • 59
38

QuerySet.explain(), available in Django 2.1.0 and above, is now the official way to explain queries.

orn688
  • 830
  • 1
  • 7
  • 10
19

Just a slight modification to guidoism's answer. This prevents getting a ProgrammingError: syntax error at or near ... error caused by the parameters not being correctly escaped in the raw query:

from django.db import connections
from django.db.models.query import QuerySet

class QuerySetExplainMixin:
    def explain(self):
        cursor = connections[self.db].cursor()
        query, params = self.query.sql_with_params()
        cursor.execute('explain %s' % query, params)
        return '\n'.join(r[0] for r in cursor.fetchall())

QuerySet.__bases__ += (QuerySetExplainMixin,)

To use, simply invoke explain() at the end of your queryset, e.g.:

print SomeModel.objects.filter(...).explain()
Pablo Ziliani
  • 191
  • 1
  • 4