2010-01-21 13 views
29

Soy principalmente un desarrollador de ActionScript y de ninguna manera un experto en SQL, pero de vez en cuando tengo que desarrollar cosas simples del lado del servidor. Entonces, pensé en preguntarle a personas más experimentadas sobre la pregunta en el título.¿Tiene sentido usar un índice que tenga una cardinalidad baja?

Según tengo entendido, no se gana mucho si se establece un índice en una columna que contenga algunos valores distintos. Tengo una columna que contiene un valor booleano (en realidad es un int pequeño, pero lo estoy usando como un indicador), y esta columna se utiliza en las cláusulas WHERE de la mayoría de las consultas que tengo. En un caso "promedio" teórico, la mitad de los valores de los registros será 1 y la otra mitad, 0. Entonces, en este escenario, el motor de base de datos podría evitar un escaneo completo de tabla, pero tendrá que leer muchas filas de todos modos (filas totales/2).

Entonces, ¿debería hacer de esta columna un índice?

Para el registro, estoy usando Mysql 5, pero estoy más interesado en un razonamiento general sobre por qué tiene/no tiene sentido indexar una columna que sé que tendrá una cardinalidad baja.

Gracias de antemano.

Respuesta

2

Normalmente hago una simple prueba de índice "have index" versus "do not have". Según mi experiencia, obtiene la mayor parte del rendimiento en consultas que usan ORDER BY en la columna indexada. En caso de que tenga cualquier clasificación en esa columna, es muy probable que la indexación le ayude.

+0

Gracias por su respuesta. En este caso, no estoy ordenando esa columna. Está solo allí para marcar un registro como habilitado/deshabilitado. Lo estoy usando para borrado suave, básicamente. Es por eso que tengo que usarlo en la cláusula WHERE de la mayoría de las consultas. –

2

En mi humilde opinión es de utilidad limitada. Supongo que en la mayoría de los casos hay otros criterios que está usando en sus consultas, además de la bandera que probablemente ayude mucho más.

Al 50%, probablemente haré algunos benchmarking con/sin y veré si hace mucha diferencia.

8

Podría valer la pena incluir el campo booleano en un índice compuesto. Por ejemplo, si usted tiene una gran mesa de mensajes que normalmente necesitan ser ordenada por fecha, sino que también tienen un valor lógico campo eliminados, lo que a menudo consultar así:

SELECT ... FROM Messages WHERE Deleted = 0 AND Date BETWEEN @start AND @end 

Definitivamente va a beneficiarse de tener un índice compuesto en el Suprimido y Fecha campos.

+0

Gracias. Tal vez debería investigar un poco sobre los índices compuestos (solo sé que existen, pero que en realidad no los he usado mucho). Estoy usando esta columna de una manera muy similar a su código de muestra (aunque hay uniones y otras cosas, pero la cláusula WHERE siempre tiene esta bandera para marcar la eliminación suave). –

56

Un índice puede ayudar incluso en los campos de baja cardinalidad si:

  1. Cuando uno de los valores posibles es muy poco frecuente en comparación con los otros valores y que la búsqueda de la misma.

    Por ejemplo, hay mujeres ciegas muy pocos colores, por lo que esta consulta:

    SELECT * 
    FROM color_blind_people 
    WHERE gender = 'F' 
    

    sería más probablemente se beneficiarían de un índice en gender.

  2. Cuando los valores tienden a agruparse en el orden de la tabla:

    SELECT * 
    FROM records_from_2008 
    WHERE year = 2010 
    LIMIT 1 
    

    Aunque sólo hay 3 años distintas aquí, son muy probablemente añaden registros con años anteriores primeros tantos y tantos registros tendría que ser escaneado antes de devolver el primer registro 2010 si no fuera por el índice.

  3. Cuando necesite ORDER BY/LIMIT:

    SELECT * 
    FROM people 
    ORDER BY 
         gender, id 
    LIMIT 1 
    

    Sin el índice, se requeriría un filesort. Aunque está algo optimizado para el LIMIT, aún necesitaría un escaneo de tabla completo.

  4. Cuando el índice cubre todos los campos utilizados en la consulta:

    CREATE INDEX (low_cardinality_record, value) 
    
    SELECT SUM(value) 
    FROM mytable 
    WHERE low_cardinality_record = 3 
    
  5. Cuando necesite DISTINCT:

    SELECT DISTINCT color 
    FROM tshirts 
    

    MySQL utilizará INDEX FOR GROUP-BY, y si usted tiene pocos colores, esta consulta será instantáneo incluso con millones de registros.

    Este es un ejemplo de un escenario en el que el índice en un campo de cardinalidad baja es más más eficiente que en un campo de cardinalidad alta.

Tenga en cuenta que si DML rendimiento no es mucho de un problema, entonces es seguro para crear el índice.

Si el optimizador considera que el índice es ineficaz, el índice simplemente no se utilizará.

Cuestiones relacionadas