2009-06-26 42 views
42

En ActiveRecord hay dos formas de declarar índices de varias columnas:Índice de varias columnas en ActiveRecord

add_index :classifications, [:species, :family, :trivial_names]
add_index :classifications, :species 
add_index :classifications, :family 
add_index :classifications, :trivial_names

¿Hay alguna diferencia entre la primera aproximación y el segundo? Si es así, ¿cuándo debería usar el primero y cuándo el segundo?

+0

Gracias, Collimarco, por seleccionar mi respuesta como "la respuesta". –

Respuesta

84

Está comparando un índice compuesto con un conjunto de índices independientes. Ellos son simplemente diferentes.

Piénselo de esta manera: un índice compuesto le da una búsqueda rápida del primer campo en un conjunto anidado de campos seguido de una búsqueda rápida del segundo campo dentro de SÓLO los registros ya seleccionados por el primer campo, seguido de una búsqueda rápida del tercer campo; nuevamente, solo dentro de los registros seleccionados por los dos índices anteriores.

Tomemos un ejemplo. Su motor de base de datos no tomará más de 20 pasos para encontrar un valor único dentro de 1,000,000 de registros (si la memoria sirve) si está usando un índice. Esto es cierto ya sea que esté usando un índice compuesto o independiente, SÓLO para el primer campo ("especie" en su ejemplo, aunque creo que querría Familia, Especie y, a continuación, Nombre común).

Ahora, digamos que hay 100.000 registros coincidentes para este primer valor de campo. Si solo tiene índices únicos, cualquier búsqueda dentro de estos registros tomará 100.000 pasos: uno para cada registro recuperado por el primer índice. Esto se debe a que el segundo índice no se utilizará (en la mayoría de las bases de datos, esto es una simplificación) y se debe usar una combinación de fuerza bruta.

Si usted tiene un índice compuesto entonces su búsqueda es mucho más rápido debido a que su segunda búsqueda campo tendrá un índice dentro de la primera serie de valores. En este caso, no necesitará más de 17 pasos para llegar a su primer valor coincidente en el campo 2 dentro de las 100.000 coincidencias en el campo 1 (log base 2 de 100,000).

Entonces: se necesitan pasos para encontrar un registro único de una base de datos de 1,000,000 de registros usando un índice compuesto en 3 campos anidados donde el primero recupera 100,000 y el segundo recupera 10,000 = 20 + 17 + 14 = 51 pasos.

Pasos necesarios en las mismas condiciones con solo índices independientes = 20 + 100,000 + 10,000 = 110,020 pasos.

Gran diferencia, ¿eh?

Ahora, no haga vuelva loco poniendo índices compuestos en todas partes. En primer lugar, son caros en inserciones y actualizaciones. En segundo lugar, solo se utilizan si realmente busca datos anidados (para otro ejemplo, los utilizo cuando obtengo datos de inicios de sesión para un cliente en un rango de fechas determinado). Además, no valen la pena si está trabajando con conjuntos de datos relativamente pequeños.

Finalmente, verifique la documentación de su base de datos. Las bases de datos se han vuelto extremadamente sofisticadas en cuanto a la capacidad de desplegar índices en estos días y el escenario de la Base de datos 101 que describí anteriormente puede no ser válido para algunos (aunque siempre lo desarrollo como si lo hiciera, así sé lo que obtengo).

+0

¡Gracias por la explicación! Vea lo que le pregunté al Sr. Matt: la cláusula WHERE contiene OR. En este caso, ¿es útil un índice compuesto? Diría que no, porque la base de datos siempre debe buscar todos los elementos y no solo las filas que resultan de la primera condición (hubiera sido diferente si existiera el operador AND porque "filtra" las filas y reduce el alcance) . ¿Me equivoco? – collimarco

+3

collimarco: en el ejemplo que proporcione al Sr. Matt, los índices independientes proporcionarían un mejor rendimiento ya que cada uno se usaría de forma independiente como parte del plan de ejecución de SQL. Piénselo de esta manera: Y es compositivo, O es independiente. Para dar otro ejemplo, si su cláusula where fuera "DÓNDE (Familia = X Y Especies = Y) O (NombreComún = Z)", entonces desearía un índice compuesto en Especies Familiares y un índice independiente en NombreComún. –

+0

BTW: los planes de ejecución de SQL están disponibles en bases de datos más sofisticadas como SQL Server y Oracle y pueden ser muy valiosos como herramienta de enseñanza (para ayudarlo a ver lo que ocurre bajo las cubiertas mientras el DB intenta optimizar su plan de búsqueda) como un mecanismo para probar varias estrategias de indexación. –

1

From the docs:

Al crear un índice en múltiples columnas, la primera columna se utiliza como un nombre para el índice. Por ejemplo, cuando especifica un índice en dos columnas [: primero,: último], el DBMS crea un índice para ambas columnas, así como un índice para la primera columna: primero. Usar el primer nombre para este índice tiene sentido, porque nunca tendrá que crear un índice singular con este nombre.

Utilice el primer método al crear un índice compuesto, y el segundo al crear índices en atributos individuales.

Hay algunos buenos puntos here on when to use compound indexes, pero la esencia es que son buenos cuando se utiliza un en múltiples atributos. Tenga en cuenta que deben usarse junto con otros índices (siempre indexe sus claves antiguas), no como un reemplazo.

+0

Gracias! Pero ... ¿cuándo tiene sentido usar un índice compuesto en lugar de un índice en un solo atributo? ¿Me puede dar algunos ejemplos? – collimarco

+0

He actualizado mi respuesta – Codebeef

+0

Has dicho que no los utilices como reemplazo, pero ¿qué ocurre si solo los uso en esta consulta: SELECCIONAR * FROM clasificaciones DONDE especies COMO '% sth%' O familia LIKE '% sth%' O trivial_names LIKE '% sth%' En este caso, ¿es correcto usar solo el índice compuesto? – collimarco

10

Los dos enfoques son diferentes. El primero crea un único índice en tres atributos, el segundo crea tres índices de atributo único. Los requisitos de almacenamiento serán diferentes, aunque sin distribuciones no es posible decir cuál sería más grande.

Indexar tres columnas [A, B, C] funciona bien cuando necesita acceder para los valores de A, A + B y C. No será bueno si su consulta (o encuentra condiciones o lo que sea) no hace referencia a A.

Cuando A, B y C se indexan por separado, algunos optimizadores de consultas DBMS considerarán combinar dos o más índices (asunto a la estimación de la eficiencia del optimizador) para dar un resultado similar a un solo índice de múltiples columnas.

Supongamos que tiene algún sistema de comercio electrónico. Desea consultar pedidos por fecha_compra, ID_cliente y, a veces, ambos. Comenzaría por crear dos índices: uno para cada atributo.

Por otro lado, si siempre especifica purchase_date y customer_id, entonces un solo índice en ambas columnas probablemente sea más eficiente. El pedido es significativo: si también desea consultar pedidos para todas las fechas para un cliente, haga que customer_id sea la primera columna del índice.

Cuestiones relacionadas