Decir que tengo una relación 1-a-N (person_id, pet_id)
. Tengo una tabla donde pet_id
está la clave principal.
Entiendo que un índice secundario InnoDB es esencialmente un árbol B donde los valores son los valores de clave primaria correspondientes para la fila.
Ahora, supongamos que una persona puede tener miles de mascotas y, a menudo, quiero las mascotas de una persona en orden pet_id
. Entonces sería importante si los registros en el índice secundario se ordenan por (person_id, pet_id)
o solo person_id
con los pet_id
's para eso person_id
sin clasificar. Adivinando lo posterior.
Entonces, si person_id
no es único, ¿los registros están ordenados físicamente (person_id, pet_id)
o SOLO pet_id
?
Gracias
mysql
innodb
primary-key
clustered-index
usuario3391564
fuente
fuente
person_id
no es único, ¿los registros están ordenados físicamente(person_id, pet_id)
o SOLOperson_id
?"Respuestas:
No. Si su tabla tiene el motor InnoDB y
PRIMARY KEY
es(pet_id)
, entonces definir un índice secundario como(person_id)
o(person_id, pet_id)
no hace ninguna diferencia.El índice también incluye la
pet_id
columna, por lo que los valores se ordenan como(person_id, pet_id)
en ambos casos.Una consulta como la que tienes:
necesitará acceder solo al índice para obtener los valores y aún más, no tendrá que hacer ningún tipo, ya que los
pet_id
valores ya están ordenados en el índice. Puede verificar esto mirando los planes de ejecución (EXPLAIN
):Primero, intentamos con una tabla MyISAM:
¡Observe el clasificador de archivos!
Ahora, MyISAM con índice compuesto:
Filesort se ha ido , como se esperaba.
Ahora intentemos lo mismo con el motor InnoDB:
¡No hay clasificación de archivos tampoco! Aunque el índice no tiene explícitamente la
pet_id
columna, los valores están allí y ordenados. Puede verificar que si define el índice con(person_id, pet_id)
, elEXPLAIN
es idéntico.Vamos a hacerlo, con InnoDB y el índice compuesto:
Planes idénticos al caso anterior.
Para estar 100% seguro, también ejecuto los últimos 2 casos (motor InnoDB, con índices únicos y compuestos) que permiten la
file_per_table
configuración y agregan algunos miles de filas en la tabla:En ambos casos, al verificar los tamaños de archivo reales, se obtienen resultados idénticos :
fuente
(<some_column>)
y(<some_column>, <pk>)
porqueON (<some_column>)
es equivalente aON (<some_column>) INCLUDE (<pk>)
noON (<some_column>, <pk>)
. En la mayoría de los casos, esto tiene una importancia prácticamente nula, pero si su PK es aleatoria (es decir, un UUID),ON (<s_c>,<pk>)
puede generar una fragmentación adicional o si su PK es significativa además de ser una clave y podríaORDER BY s_c, pk
ser que ese tipo será más rápido como índice Ya está completamente en orden.INCLUDE (columns)
embargo, MySQL no tiene funcionalidad. Esa es otra razón por la que concluí que el(s_c)
índice es equivalente a(s_c, pk)
.De acuerdo con la documentación de MySQL sobre los índices agrupados y secundarios
Por lo tanto, agregar la CLAVE PRIMARIA a un índice secundario es definitivamente redundante. Su entrada de índice le gustaría
(person_id, pet_id, pet_id)
. Esto también hincharía innecesariamente el índice secundario al tener 2 copias dePRIMARY KEY
.Para el índice con
(person_id)
, si tuviera que ejecutar una consulta como estaEl
PRIMARY KEY
estaría completamente involucrado en esta consulta y produce los resultados ordenados dePRIMARY KEY
todos modos. Desde un punto de vista físico, las filas están ordenadas por orden de inserción. Si pet_id es AUTO_INCREMENT, entonces se ordena por el número automático.fuente
(owner_id, pet_id)
pero puede crear una clave(vet_id, pet_id[, owner_id])
para utilizar un orden de columna diferente.Consejo 1:
Es perfectamente válido. Tiene la ventaja de rendimiento de ser más eficiente cuando muchas consultas necesitan encontrar varias filas
WHERE x = 123
. Es decir, es un poco más eficiente que lo 'obvio'La única regla sobre
AUTO_INCREMENT
(para InnoDB) es queid
debe ser la primera columna de algún índice. Tenga en cuenta que esta regla no dice nada sobrePRIMARY
oUNIQUE
o 'única columna'.La sugerencia es útil para tablas enormes que a menudo se obtienen
x
junto con otras cosas.Consejo 2: suponga que tiene
Este es un índice de "cobertura":
Es decir, toda la consulta se puede hacer dentro del índice BTree. El EXPLICAR dirá "Usando índice".
fuente