[Django] #23367: MySQL composite indexes create duplicate indexes (ManyToManyField, unique_together)

29 views
Skip to first unread message

Django

unread,
Aug 26, 2014, 6:07:27 PM8/26/14
to django-...@googlegroups.com
#23367: MySQL composite indexes create duplicate indexes (ManyToManyField,
unique_together)
----------------------------------------------+--------------------
Reporter: jdufresne | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
This ticket is similar in spirit to #3030 but covers a different
combination and case.

See the blog article http://www.mysqlperformanceblog.com/2012/06/20/find-
and-remove-duplicate-indexes/ for information on why these tables contain
duplicate indexes and why this creates a sub-optimal database.
Specifically the section titled "Redundant keys on composite indexes".

In MySQL, given the following model definition in `myapp/models.py`,
Django `syncdb` creates duplicate indexes.

{{{
class ModelA(models.Model):
name = models.CharField(max_length=100)

class ModelB(models.Model):
modela = models.ManyToManyField(ModelA)

class ModelC(models.Model):
modela = models.ForeignKey(ModelA)
modelb = models.ForeignKey(ModelB)

class Meta:
unique_together = ('modela', 'modelb')
}}}

The first duplicate index appears in the implicit table created by
`ManyToManyField`:

{{{
CREATE TABLE `myapp_modelb_modela` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`modelb_id` int(11) NOT NULL,
`modela_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `modelb_id` (`modelb_id`,`modela_id`),
KEY `myapp_modelb_modela_db457816` (`modelb_id`),
KEY `myapp_modelb_modela_a4d53239` (`modela_id`),
CONSTRAINT `modelb_id_refs_id_6c09d9ee` FOREIGN KEY (`modelb_id`)
REFERENCES `myapp_modelb` (`id`),
CONSTRAINT `modela_id_refs_id_952611a9` FOREIGN KEY (`modela_id`)
REFERENCES `myapp_modela` (`id`)
)
}}}

In the `UNIQUE KEY modelb_id`, `modelb_id` is the first field in the
composite index. MySQL is perfectly capable of using this as an index on
both the field `modelb_id` and the composite `(modelb_id, modela_id)`.
Ideally the second index, `KEY myapp_modelb_modela_db457816 (modelb_id)`
would not be created at all.

The second duplicate index comes from `ModelC` and the `unique_together`
constraint. This creates the database table:

{{{
CREATE TABLE `myapp_modelc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`modela_id` int(11) NOT NULL,
`modelb_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `modela_id` (`modela_id`,`modelb_id`),
KEY `myapp_modelc_a4d53239` (`modela_id`),
KEY `myapp_modelc_db457816` (`modelb_id`),
CONSTRAINT `modela_id_refs_id_f6e0e692` FOREIGN KEY (`modela_id`)
REFERENCES `myapp_modela` (`id`),
CONSTRAINT `modelb_id_refs_id_8e5b78f5` FOREIGN KEY (`modelb_id`)
REFERENCES `myapp_modelb` (`id`)
)
}}}

Here, the index `KEY myapp_modelc_a4d53239 (modela_id)` is a duplicate as
modela_id appears as the first column in the composite `UNIQUE KEY`.

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

Django

unread,
Aug 27, 2014, 8:52:29 AM8/27/14
to django-...@googlegroups.com
#23367: MySQL composite indexes create duplicate indexes (ManyToManyField,
unique_together)
-------------------------------------+-------------------------------------
Reporter: jdufresne | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: master
(models, ORM) | Resolution: duplicate
Severity: Normal | Triage Stage:
Keywords: | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

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

* status: new => closed
* needs_better_patch: => 0
* resolution: => duplicate
* needs_tests: => 0
* needs_docs: => 0


Comment:

Duplicate of #22125.

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

Reply all
Reply to author
Forward
0 new messages