[Django] #28574: Add a Queryset.explain() method

28 views
Skip to first unread message

Django

unread,
Sep 6, 2017, 3:21:54 PM9/6/17
to django-...@googlegroups.com
#28574: Add a Queryset.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom | Owner: nobody
Type: New | Status: new
feature |
Component: Database | Version: master
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
When diagnosing slow queries it would be handy to have an `explain` method
on the queryset. Currently if you have a queryset that is performing
slowly and you want to use your databases EXPLAIN query to see why, you
have to print the querysets query attribute, copy and paste the often
verbose string into a database shell, add the appropriate explain syntax,
fix any parameters that may be missing and execute it. This can be quite
annoying.

Every database that is supported in core supports this, usually by adding
`EXPLAIN` before the query. Simply returning whatever the database gives
you (which is vastly different per vendor and even version) could be a
good improvement.

--
Ticket URL: <https://code.djangoproject.com/ticket/28574>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 7, 2017, 10:01:32 AM9/7/17
to django-...@googlegroups.com
#28574: Add a Queryset.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Srinivas Reddy Thatiparthy):

+1 for this .

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:1>

Django

unread,
Sep 7, 2017, 12:27:08 PM9/7/17
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method

-------------------------------------+-------------------------------------
Reporter: Tom | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Unreviewed => Accepted


Comment:

It looks reasonable at first glance.

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:2>

Django

unread,
Sep 9, 2017, 1:29:03 PM9/9/17
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom | Owner: Tom
Type: New feature | Status: assigned

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tom):

* cc: Tom (added)
* owner: nobody => Tom
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:3>

Django

unread,
Sep 10, 2017, 10:39:10 AM9/10/17
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------

Reporter: Tom | Owner: Tom
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tom):

PR: https://github.com/django/django/pull/9053

On any select queryset you can do `print(qs.explain())` and it will print
the databases EXPLAIN output. There is a `verbose` and a `format` flag for
backends that support it, e.g on Mysql/Postgres
`print(qs.explain(verbose=True, format='json'))`

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:4>

Django

unread,
Sep 29, 2017, 10:43:26 AM9/29/17
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------

Reporter: Tom | Owner: Tom
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tom):

* has_patch: 0 => 1


Comment:

I've updated the patch to include documentation. This works well on all
databases except MySQL, which returns a table structure rather than a
human-readable strings like PostgreSQL. Without the pseudo-table headers
it's not very useful, but it could be a lot more effort to add support for
this (we would have to deal with lining up the column headers with the
values, add support for returning the column names from the `execute_sql`
function).

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:5>

Django

unread,
Dec 3, 2017, 5:41:40 AM12/3/17
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes

Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Martin):

* needs_better_patch: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:6>

Django

unread,
Dec 9, 2017, 9:39:55 AM12/9/17
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tom Forbes):

* needs_better_patch: 1 => 0


--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:7>

Django

unread,
Mar 5, 2018, 4:58:46 AM3/5/18
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

* stage: Accepted => Ready for checkin


Comment:

Patch looks good.

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:8>

Django

unread,
Mar 5, 2018, 8:49:28 AM3/5/18
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

* needs_better_patch: 0 => 1
* stage: Ready for checkin => Accepted


Comment:

The new tests fail on Oracle. Needs resolving. (Hopefully good to go
then.)

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:9>

Django

unread,
Mar 18, 2018, 1:02:56 PM3/18/18
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tom Forbes):

* needs_better_patch: 1 => 0


--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:10>

Django

unread,
Mar 18, 2018, 1:07:28 PM3/18/18
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tom Forbes):

I don't see how we can add support for Oracle, the way explaining query
plans works is significantly different from any other implementation,
including the fact that you cannot use SQL parameterized queries.

I've modified the patch to simply disable this feature on Oracle for now.

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:11>

Django

unread,
Mar 19, 2018, 10:39:05 AM3/19/18
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

* stage: Accepted => Ready for checkin


Comment:

This looks ready to go. Good work Tom!

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:12>

Django

unread,
Apr 19, 2018, 11:13:44 AM4/19/18
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: closed

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: fixed

Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"c1c163b42717ed5e051098ebf0e2f5c77810f20e" c1c163b4]:
{{{
#!CommitTicketReference repository=""
revision="c1c163b42717ed5e051098ebf0e2f5c77810f20e"
Fixed #28574 -- Added QuerySet.explain().
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:13>

Django

unread,
Oct 23, 2019, 8:09:25 AM10/23/19
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: closed
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"a5c5ae7d9120cba3206a0e31d23c22f4a14a10df" a5c5ae7d]:
{{{
#!CommitTicketReference repository=""
revision="a5c5ae7d9120cba3206a0e31d23c22f4a14a10df"
Refs #28574 -- Used feature flag for PostgreSQL version check.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:14>

Django

unread,
Jul 5, 2021, 4:59:48 AM7/5/21
to django-...@googlegroups.com
#28574: Add a QuerySet.explain() method
-------------------------------------+-------------------------------------
Reporter: Tom Forbes | Owner: Tom
| Forbes
Type: New feature | Status: closed
Component: Database layer | Version: dev

(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"b3b04ad2111f1e3eb0640cd5d51d4391655317ce" b3b04ad2]:
{{{
#!CommitTicketReference repository=""
revision="b3b04ad2111f1e3eb0640cd5d51d4391655317ce"
Refs #28574 -- Added test for XML format output to Queryset.explain().
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28574#comment:15>

Reply all
Reply to author
Forward
0 new messages