Opened 11 years ago
Closed 11 years ago
#23367 closed Bug (duplicate)
MySQL composite indexes create duplicate indexes (ManyToManyField, unique_together)
| Reported by: | Jon Dufresne | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
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.
Duplicate of #22125.