Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fixed #22125 - Eliminates redundant index creation #2578

Closed
wants to merge 8 commits into from

2 participants

@bwreilly

The first field defined as unique_together automatically has an index generated for it in all known backends. This removes an additional CREATE INDEX on model generation for that field. The behavior is in a separate method for those cases where a particular backend may wish to override it.

Tracker issue

@timgraham
Owner

I'm not sure about the fix, but it would be better if you could squash the commits.

@timgraham
Owner

Please see the ticket for comments.

@timgraham timgraham closed this
@bwreilly bwreilly deleted the ClipCard:master branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 24 additions and 1 deletion.
  1. +15 −1 django/db/backends/schema.py
  2. +9 −0 tests/schema/tests.py
View
16 django/db/backends/schema.py
@@ -176,6 +176,18 @@ def quote_value(self, value):
"""
raise NotImplementedError()
+ def unique_together_indexes(self, model):
+ """Returns fields that will already have an index by virtue of being
+ the first field in a unique_together constraint.
+
+ Override to disable by returning an empty iterable"""
+ indexed = set()
+ for field_names in model._meta.unique_together:
+ name = field_names[0]
+ field = model._meta.get_field_by_name(name)[0]
+ indexed.add(field)
+ return indexed
+
# Actions
def create_model(self, model):
@@ -186,6 +198,8 @@ def create_model(self, model):
# Create column SQL, add FK deferreds if needed
column_sqls = []
params = []
+
+ already_indexed = self.unique_together_indexes(model)
for field in model._meta.local_fields:
# SQL
definition, extra_params = self.column_sql(model, field)
@@ -201,7 +215,7 @@ def create_model(self, model):
definition += " %s" % col_type_suffix
params.extend(extra_params)
# Indexes
- if field.db_index and not field.unique:
+ if field.db_index and not (field.unique or field in already_indexed):
self.deferred_sql.append(
self.sql_create_index % {
"name": self._create_index_name(model, [field.column], suffix=""),
View
9 tests/schema/tests.py
@@ -552,6 +552,15 @@ def test_unique_together(self):
self.assertRaises(IntegrityError, UniqueTest.objects.create, year=2012, slug="foo")
UniqueTest.objects.all().delete()
+ def test_unique_together_indexes(self):
+ """
+ Get the fields that do not need another index
+ """
+ with connection.schema_editor() as editor:
+ fields = editor.unique_together_indexes(UniqueTest)
+ expected = set([UniqueTest._meta.get_field_by_name("year")[0]])
+ self.assertSequenceEqual(fields, expected)
+
def test_index_together(self):
"""
Tests removing and adding index_together constraints on a model.
Something went wrong with that request. Please try again.