#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.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.8547890481cd0d3037308359993d2b29%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to