Fixed #30913 -- Added support for covering indexes on PostgreSQL 11+.

This commit is contained in:
Hannes Ljungberg 2019-10-31 13:33:53 +01:00 committed by Mariusz Felisiak
parent f997b5e6ae
commit 8c7992f658
20 changed files with 719 additions and 41 deletions

View file

@ -73,7 +73,7 @@ constraint.
``UniqueConstraint``
====================
.. class:: UniqueConstraint(*, fields, name, condition=None, deferrable=None)
.. class:: UniqueConstraint(*, fields, name, condition=None, deferrable=None, include=None)
Creates a unique constraint in the database.
@ -145,3 +145,26 @@ enforced immediately after every command.
Deferred unique constraints may lead to a `performance penalty
<https://www.postgresql.org/docs/current/sql-createtable.html#id-1.9.3.85.9.4>`_.
``include``
-----------
.. attribute:: UniqueConstraint.include
.. versionadded:: 3.2
A list or tuple of the names of the fields to be included in the covering
unique index as non-key columns. This allows index-only scans to be used for
queries that select only included fields (:attr:`~UniqueConstraint.include`)
and filter only by unique fields (:attr:`~UniqueConstraint.fields`).
For example::
UniqueConstraint(name='unique_booking', fields=['room', 'date'], include=['full_name'])
will allow filtering on ``room`` and ``date``, also selecting ``full_name``,
while fetching data only from the index.
``include`` is supported only on PostgreSQL.
Non-key columns have the same database restrictions as :attr:`Index.include`.

View file

@ -21,7 +21,7 @@ options`_.
``Index`` options
=================
.. class:: Index(fields=(), name=None, db_tablespace=None, opclasses=(), condition=None)
.. class:: Index(fields=(), name=None, db_tablespace=None, opclasses=(), condition=None, include=None)
Creates an index (B-Tree) in the database.
@ -137,3 +137,40 @@ indexes records with more than 400 pages.
The ``condition`` argument is ignored with MySQL and MariaDB as neither
supports conditional indexes.
``include``
-----------
.. attribute:: Index.include
.. versionadded:: 3.2
A list or tuple of the names of the fields to be included in the covering index
as non-key columns. This allows index-only scans to be used for queries that
select only included fields (:attr:`~Index.include`) and filter only by indexed
fields (:attr:`~Index.fields`).
For example::
Index(name='covering_index', fields=['headline'], include=['pub_date'])
will allow filtering on ``headline``, also selecting ``pub_date``, while
fetching data only from the index.
Using ``include`` will produce a smaller index than using a multiple column
index but with the drawback that non-key columns can not be used for sorting or
filtering.
``include`` is ignored for databases besides PostgreSQL.
:attr:`Index.name` is required when using ``include``.
See the PostgreSQL documentation for more details about `covering indexes`_.
.. admonition:: Restrictions on PostgreSQL
PostgreSQL 11+ only supports covering B-Tree indexes, and PostgreSQL 12+
also supports covering :class:`GiST indexes
<django.contrib.postgres.indexes.GistIndex>`.
.. _covering indexes: https://www.postgresql.org/docs/current/indexes-index-only-scans.html