Скажем , у меня есть отношения 1-к-N (person_id, pet_id)
. У меня есть таблица, где pet_id
находится первичный ключ.
Я понимаю, что вторичный индекс InnoDB - это, по сути, B-дерево, где значения являются соответствующими значениями первичного ключа для строки.
Теперь предположим, что у одного человека могут быть тысячи домашних животных, и я часто хочу, чтобы домашние животные человека были в порядке pet_id
. Тогда будет иметь значение, будут ли записи во вторичном индексе отсортированы по (person_id, pet_id)
или просто person_id
с тем pet_id
, что person_id
не отсортировано . Догадываюсь позже.
Итак, если person_id
запись не уникальна, физически отсортированы записи (person_id, pet_id)
или просто pet_id
?
Спасибо
mysql
innodb
primary-key
clustered-index
user3391564
источник
источник
person_id
не уникальны, физически отсортированы записи(person_id, pet_id)
или простоperson_id
?»Ответы:
Нет. Если ваша таблица имеет механизм InnoDB и имеет значение
PRIMARY KEY
is(pet_id)
, то определение вторичного индекса как(person_id)
или(person_id, pet_id)
не имеет значения.Индекс также включает
pet_id
столбец, поэтому значения сортируются как(person_id, pet_id)
в обоих случаях.Запрос, подобный тому, который у вас есть:
для получения значений потребуется доступ только к индексу, и даже больше, для этого не нужно выполнять никакой сортировки, поскольку
pet_id
значения уже отсортированы в индексе. Вы можете убедиться в этом, посмотрев планы выполнения (EXPLAIN
):Сначала мы попробуем с таблицей MyISAM:
Обратите внимание на сортировку файлов!
Теперь MyISAM с составным индексом:
Файловая сортировка прошла , как и ожидалось.
Теперь давайте попробуем то же самое с движком InnoDB:
Также нет сортировки файлов! Несмотря на то, что индекс не имеет явно
pet_id
столбца, значения там и отсортированы. Вы можете проверить, что если вы определяете индекс с помощью(person_id, pet_id)
,EXPLAIN
он идентичен.Давайте на самом деле сделаем это, используя InnoDB и составной индекс:
Идентичные планы с предыдущим делом.
Чтобы быть на 100% уверенным, я также запускаю последние 2 случая (механизм InnoDB, с единичными и составными индексами), включив
file_per_table
настройку и добавив несколько тысяч строк в таблицу:В обоих случаях проверка фактических размеров файлов дает одинаковые результаты :
источник
(<some_column>)
и(<some_column>, <pk>)
потому , чтоON (<some_column>)
эквивалентно ,ON (<some_column>) INCLUDE (<pk>)
а неON (<some_column>, <pk>)
. В большинстве случаев это имеет практически нулевое значение, но если ваш PK является случайным (то есть UUID), то этоON (<s_c>,<pk>)
может привести к дополнительной фрагментации или если ваш PK имеет значение, отличное от того, чтобы быть ключом, и вы могли быORDER BY s_c, pk
тогда такие сортировки быть быстрее, чем индекс уже полностью в порядке.INCLUDE (columns)
функциональности, хотя. Это еще одна причина, по которой я пришел к выводу, что(s_c)
индекс эквивалентен(s_c, pk)
.Согласно документации MySQL по кластерным и вторичным индексам
Следовательно, добавление PRIMARY KEY к вторичному индексу однозначно избыточно. Ваша индексная запись хотела бы
(person_id, pet_id, pet_id)
. Это также излишне раздувает вторичный индекс, имея 2 копииPRIMARY KEY
.Для индекса с
(person_id)
, если вы должны были выполнить запрос, как этоОн
PRIMARY KEY
будет полностью вовлечен в этот запрос и выдаст результаты, упорядоченные вPRIMARY KEY
любом случае. С физической точки зрения строки упорядочены по порядку вставки. Если pet_id это AUTO_INCREMENT, то это порядок по номеру авто.источник
(owner_id, pet_id)
но вы можете создать ключ(vet_id, pet_id[, owner_id])
для использования другого порядка столбцов.Совет 1:
совершенно верно. Он имеет преимущество в производительности, заключающееся в большей эффективности, когда во многих запросах необходимо найти несколько строк
WHERE x = 123
. То есть он немного более эффективен, чем «очевидный»Единственное правило о
AUTO_INCREMENT
(для InnoDB) заключается в том, что онid
должен быть первым столбцом в некотором индексе. Обратите внимание, что это правило ничего не говорит оPRIMARY
илиUNIQUE
или «только столбец».Совет полезен для огромных таблиц, которые часто выбираются
x
вместе с другими вещами.Совет 2: Предположим, у вас есть
Это индекс «покрытия»:
То есть весь запрос может быть выполнен внутри индекса BTree. Объяснение скажет "Использование индекса".
источник