- ¿Cuándo debo usar un índice compuesto en una base de datos?
- ¿Cuáles son las ramificaciones de rendimiento al usar un índice compuesto)?
- ¿Por qué debería usar un índice compuesto?
Por ejemplo, tengo una homes
tabla:
CREATE TABLE IF NOT EXISTS `homes` (
`home_id` int(10) unsigned NOT NULL auto_increment,
`sqft` smallint(5) unsigned NOT NULL,
`year_built` smallint(5) unsigned NOT NULL,
`geolat` decimal(10,6) default NULL,
`geolng` decimal(10,6) default NULL,
PRIMARY KEY (`home_id`),
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
) ENGINE=InnoDB ;
¿Tiene sentido para mí usar un índice compuesto para ambos geolat
y geolng
, de modo que:
Sustituyo:
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
con:
KEY `geolat_geolng` (`geolat`, `geolng`)
Si es así:
- ¿Por qué?
- ¿Cuál es la ramificación del rendimiento al usar un índice compuesto)?
ACTUALIZAR:
Dado que muchas personas lo han declarado totalmente dependiente de las consultas que realizo, a continuación es la consulta más común realizada:
SELECT * FROM homes
WHERE geolat BETWEEN ??? AND ???
AND geolng BETWEEN ??? AND ???
ACTUALIZACIÓN 2:
Con el siguiente esquema de base de datos:
CREATE TABLE IF NOT EXISTS `homes` (
`home_id` int(10) unsigned NOT NULL auto_increment,
`primary_photo_group_id` int(10) unsigned NOT NULL default '0',
`customer_id` bigint(20) unsigned NOT NULL,
`account_type_id` int(11) NOT NULL,
`address` varchar(128) collate utf8_unicode_ci NOT NULL,
`city` varchar(64) collate utf8_unicode_ci NOT NULL,
`state` varchar(2) collate utf8_unicode_ci NOT NULL,
`zip` mediumint(8) unsigned NOT NULL,
`price` mediumint(8) unsigned NOT NULL,
`sqft` smallint(5) unsigned NOT NULL,
`year_built` smallint(5) unsigned NOT NULL,
`num_of_beds` tinyint(3) unsigned NOT NULL,
`num_of_baths` decimal(3,1) unsigned NOT NULL,
`num_of_floors` tinyint(3) unsigned NOT NULL,
`description` text collate utf8_unicode_ci,
`geolat` decimal(10,6) default NULL,
`geolng` decimal(10,6) default NULL,
`display_status` tinyint(1) NOT NULL,
`date_listed` timestamp NOT NULL default CURRENT_TIMESTAMP,
`contact_email` varchar(100) collate utf8_unicode_ci NOT NULL,
`contact_phone_number` varchar(15) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`home_id`),
KEY `customer_id` (`customer_id`),
KEY `city` (`city`),
KEY `num_of_beds` (`num_of_beds`),
KEY `num_of_baths` (`num_of_baths`),
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
KEY `account_type_id` (`account_type_id`),
KEY `display_status` (`display_status`),
KEY `sqft` (`sqft`),
KEY `price` (`price`),
KEY `primary_photo_group_id` (`primary_photo_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ;
Usando el siguiente SQL:
EXPLAIN SELECT homes.home_id,
address,
city,
state,
zip,
price,
sqft,
year_built,
account_type_id,
num_of_beds,
num_of_baths,
geolat,
geolng,
photo_id,
photo_url_dir
FROM homes
LEFT OUTER JOIN home_photos ON homes.home_id = home_photos.home_id
AND homes.primary_photo_group_id = home_photos.home_photo_group_id
AND home_photos.home_photo_type_id = 2
WHERE homes.display_status = true
AND homes.geolat BETWEEN -100 AND 100
AND homes.geolng BETWEEN -100 AND 100
EXPLICAR devuelve:
id select_type table type possible_keys key key_len ref rows Extra
----------------------------------------------------------------------------------------------------------
1 SIMPLE homes ref geolat,geolng,display_status display_status 1 const 2 Using where
1 SIMPLE home_photos ref home_id,home_photo_type_id,home_photo_group_id home_photo_group_id 4 homes.primary_photo_group_id 4
No entiendo cómo leer el comando EXPLAIN. ¿Esto se ve bien o mal? En este momento, NO estoy usando un índice compuesto para geolat y geolng. ¿Debo ser?
fuente
WHERE geolat BETWEEN ??? AND ??? AND geolng BETWEEN ??? AND ???
. Se detendrá después del primer campo. La respuesta de "Desbordamiento de preguntas" explica por qué.Imagine que tiene las siguientes tres consultas:
Consulta I:
Consulta II:
Consulta III:
Si tiene un índice separado por columna, las tres consultas usan índices. En MySQL, si tiene un índice compuesto (
geolat
,geolng
), solo la consulta I y la consulta II (que usa la primera parte del índice compuesto) usa índices. En este caso, la consulta III requiere una búsqueda completa en la tabla.En la sección de índices de columnas múltiples del manual, se explica claramente cómo funcionan los índices de columnas múltiples, por lo que no quiero volver a escribir el manual.
Desde la página del Manual de referencia de MySQL :
Si usa un índice separado para las columnas geolat y geolng, tiene dos índices diferentes en su tabla que puede buscar de forma independiente.
Si usa un índice compuesto, solo tiene un índice para ambas columnas:
RRN es un número de registro relativo (para simplificar, puede decir ID). Los dos primeros índices generados se separan y el tercer índice es compuesto. Como puede ver, puede buscar en base a geolng en uno compuesto ya que está indexado por geolat, sin embargo, es posible buscar por geolat o "geolat AND geolng" (ya que geolng es un índice de segundo nivel).
Además, eche un vistazo a la sección del manual Cómo MySQL usa los índices .
fuente
BETWEEN
), ¡no se consideran más campos del índice! Entonces el índice compuesto no es mejor.Podría haber una idea errónea sobre lo que hace el índice compuesto. Mucha gente piensa que el índice compuesto se puede utilizar para optimizar una consulta de búsqueda siempre que la
where
cláusula cubra las columnas indexadas, en su casogeolat
ygeolng
. Profundicemos más:Creo que sus datos sobre las coordenadas de las casas serían decimales aleatorios como tales:
Como
geolat
y losgeolng
valores apenas se repiten. Un índice compuestogeolat
ygeolng
se vería así:¡Por lo tanto, la segunda columna del índice compuesto es básicamente inútil ! La velocidad de su consulta con un índice compuesto probablemente será similar a un índice solo en la
geolat
columna.Como lo mencionó Will, MySQL proporciona soporte de extensión espacial . Un punto espacial se almacena en una sola columna en lugar de dos
lat
lng
columnas separadas . El índice espacial se puede aplicar a dicha columna. Sin embargo, la eficiencia podría ser sobrevalorada en base a mi experiencia personal. Podría ser que el índice espacial no resuelva el problema bidimensional, sino que simplemente acelere la búsqueda usando R-Trees con división cuadrática .La compensación es que un punto espacial consume mucha más memoria, ya que utiliza números de doble precisión de ocho bytes para almacenar coordenadas. Corrígeme si estoy equivocado.
fuente
Los índices compuestos son muy potentes ya que:
INTEGRIDAD DE LA ESTRUCTURA DE APLICACIÓN
Los índices compuestos no son simplemente otro tipo de índice; pueden proporcionar la estructura NECESARIA a una tabla al hacer cumplir la integridad como la Clave primaria.
Innodb de Mysql admite la agrupación y el siguiente ejemplo ilustra por qué un índice compuesto puede ser necesario.
Para crear un grupo de amigos tablas (es decir, para una red social) necesitamos 2 columnas:
user_id, friend_id
.Tabla Strcture
En virtud, una Clave primaria (PK) es única y al crear una PK compuesta, Innodb verificará automáticamente que no existan duplicados
user_id, friend_id
cuando se agrega un nuevo registro. Este es el comportamiento esperado ya que ningún usuario debería tener más de 1 registro (enlace de relación) con,friend_id = 2
por ejemplo.Sin un PK compuesto, podemos crear este esquema usando una clave sustituta:
Ahora, cada vez que se agrega un nuevo registro, tendremos que verificar que
user_id, friend_id
no exista un registro anterior con la combinación .Como tal, un índice compuesto puede hacer cumplir la integridad de la estructura.
HABILITAR CLASIFICACIÓN EN UNA ID FILTRADA
Es muy común ordenar un conjunto de registros por la hora de la publicación (marca de tiempo o fecha y hora). Por lo general, esto significa publicar en una identificación determinada. Aquí hay un ejemplo
Table User_Wall_Posts (piense si las publicaciones en el muro de Facebook)
Queremos consultar y encontrar todas las publicaciones
user_id = 10
y ordenar las publicaciones de comentarios portimestamp
(fecha).Consulta SQL
El PK compuesto le permite a Mysql filtrar y ordenar los resultados usando el índice; Mysql no tendrá que usar un archivo temporal u ordenar archivos para obtener los resultados. Sin una clave compuesta, esto no sería posible y causaría una consulta muy ineficiente.
Como tal, las claves compuestas son muy potentes y se adaptan más que el simple problema de "Quiero buscar,
column_a, column_b
así que usaré claves compuestas. Para mi esquema de base de datos actual, tengo tantas claves compuestas como claves individuales. No pase por alto uso de una clave compuesta!fuente
Los índices compuestos son útiles para
Un índice compuesto no puede manejar dos rangos. Discuto esto más a fondo en mi libro de cocina índice .
Encuentre el más cercano : si la pregunta es realmente sobre la optimización
entonces ningún índice realmente puede manejar ambas dimensiones.
En cambio, uno debe "pensar fuera de la caja". Si una dimensión se implementa a través de la partición y la otra se implementa seleccionando cuidadosamente
PRIMARY KEY
, se puede obtener una eficiencia significativamente mejor para tablas muy grandes de búsqueda de lat / lng. Mi último blog detalla cómo implementar "encontrar el más cercano" en el mundo. Incluye codigo.El
PARTITIONs
son franjas de rangos de latitud. ElPRIMARY KEY
deliberadamente comienza con la longitud, por lo que es probable que las filas útiles estén en el mismo bloque. Una rutina almacenada organiza el código desordenado para hacerorder by... limit...
y para hacer crecer el 'cuadrado' alrededor del objetivo hasta que tenga suficientes cafeterías (o lo que sea). También se encarga de los cálculos de gran círculo y el manejo de la línea de fecha y los polos.Más
He escrito otro blog; compara 5 formas de realizar búsquedas lat / lng: http://mysql.rjweb.org/doc.php/latlng#representation_choices (hace referencia al enlace anterior como una de las 5.) Una de las otras formas es esta, y señala que son óptimas para el caso particular :
Es decir, tener ambas columnas en dos índices y no tener índices de una sola columna en geolat y geolng es importante.
fuente
No hay respuesta en blanco y negro, talla única.
Debe usar un índice compuesto, cuando su carga de trabajo de consulta se beneficiaría de uno.
Debe determinar su carga de trabajo de consulta para determinar esto.
Un índice compuesto entra en juego cuando las consultas pueden satisfacerse por completo desde ese índice.
ACTUALIZACIÓN (en respuesta a la edición a la pregunta publicada): si está seleccionando * de la tabla, puede usarse el índice compuesto, puede que no. Deberá ejecutar EXPLAIN PLAN para estar seguro.
fuente
Para realizar búsquedas espaciales, necesita un algoritmo R-Tree , que permite buscar áreas geográficas muy rápidamente. Exactamente lo que necesitas para este trabajo.
Algunas bases de datos tienen índices espaciales incorporados. Una búsqueda rápida en Google muestra que MySQL 5 los tiene (que al mirar su SQL, supongo que está usando MySQL).
fuente
El índice compuesto puede ser útil cuando desea optimizar la
group by
cláusula (consulte este artículo http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html ). Por favor pon atención:fuente
GROUP BY
No fue mencionado.GROUP BY
no fue mencionado por el OP.Estoy con @Mitch, depende completamente de tus consultas. Afortunadamente, puede crear y soltar índices en cualquier momento, y puede anteponer la palabra clave EXPLAIN a sus consultas para ver si el analizador de consultas utiliza los índices.
Si está buscando un par lat / long exacto, este índice probablemente tenga sentido. Pero probablemente va a buscar casas a cierta distancia de un lugar en particular, por lo que sus consultas se verán así (ver fuente ):
y es muy probable que el índice no sea útil en absoluto. Para consultas geoespaciales, necesita algo como esto .
Actualización: con esta consulta:
El analizador de consultas podría usar un índice solo en geolat, o un índice solo en geolng, o posiblemente ambos índices. No creo que use un índice compuesto. Pero es fácil probar cada una de estas permutaciones en un conjunto de datos real y luego (a) ver lo que EXPLAIN le dice y (b) medir el tiempo que realmente lleva la consulta.
fuente