¿Qué columnas suelen ser buenos índices?

98

Como seguimiento de " ¿Qué son los índices y cómo puedo usarlos para optimizar las consultas en mi base de datos? ", Donde intento aprender sobre los índices, ¿qué columnas son buenas candidatas a índices? ¿Específicamente para una base de datos MS SQL?

Después de buscar en Google, todo lo que he leído sugiere que las columnas que generalmente aumentan y son únicas hacen un buen índice (cosas como auto_increment de MySQL), lo entiendo, pero estoy usando MS SQL y estoy usando GUID para claves primarias, así que parece que los índices no beneficiarían a las columnas GUID ...

mmattax
fuente
¿Qué tal un "libro de cocina": mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Respuestas:

110

Los índices pueden jugar un papel importante en la optimización de consultas y en la búsqueda rápida de resultados en tablas. Por lo tanto, el paso más importante es seleccionar qué columnas se indexarán. Hay dos lugares principales donde podemos considerar la indexación: columnas a las que se hace referencia en la cláusula WHERE y columnas utilizadas en las cláusulas JOIN. En resumen, estas columnas deben indexarse ​​en función de las cuales debe buscar registros particulares. Supongamos que tenemos una tabla llamada compradores donde la consulta SELECT usa índices como los siguientes:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Dado que se hace referencia a "buyer_id" en la parte SELECT, MySQL no lo usará para limitar las filas elegidas. Por lo tanto, no es muy necesario indexarlo. El siguiente es otro ejemplo un poco diferente al anterior:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

De acuerdo con las consultas anteriores first_name, las columnas last_name se pueden indexar ya que están ubicadas en la cláusula WHERE. También se puede considerar un campo adicional, country_id de la tabla de países, para la indexación porque está en una cláusula JOIN. Por lo tanto, se puede considerar la indexación en todos los campos de la cláusula WHERE o una cláusula JOIN.

La siguiente lista también ofrece algunos consejos que siempre debe tener en cuenta cuando intente crear índices en sus tablas:

  • Solo indexe las columnas que se requieren en las cláusulas WHERE y ORDER BY. La indexación de columnas en abundancia resultará en algunas desventajas.
  • Intente aprovechar las funciones de "prefijo de índice" o "índice de varias columnas" de MySQL. Si crea un índice como INDEX (primer nombre, apellido), no cree INDEX (primer nombre). Sin embargo, "prefijo de índice" o "índice de varias columnas" no se recomienda en todos los casos de búsqueda.
  • Utilice el atributo NOT NULL para aquellas columnas en las que considere la indexación, de modo que los valores NULL nunca se almacenarán.
  • Utilice la opción --log-long-format para registrar consultas que no utilizan índices. De esta manera, puede examinar este archivo de registro y ajustar sus consultas en consecuencia.
  • La declaración EXPLAIN le ayuda a revelar cómo MySQL ejecutará una consulta. Muestra cómo y en qué orden se unen las tablas. Esto puede resultar muy útil para determinar cómo escribir consultas optimizadas y si es necesario indexar las columnas.

Actualización (23 de febrero de 2015):

Cualquier índice (bueno / malo) aumenta el tiempo de inserción y actualización.

Dependiendo de sus índices (número de índices y tipo), se busca el resultado. Si su tiempo de búsqueda aumentará debido al índice, entonces es un índice incorrecto.

Probablemente en cualquier libro, la "Página de índice" podría tener una página de inicio de capítulo, un inicio de número de página de tema y también un inicio de página de subtema. Algunas aclaraciones en la página de índice ayudan, pero un índice más detallado puede confundirlo o asustarlo. Los índices también tienen memoria.

La selección de índices debería ser prudente. Tenga en cuenta que no todas las columnas requerirán index.

Somnath Muluk
fuente
Gracias Somnath, entonces, ¿implica que los índices solo deben crearse para las columnas donde planeamos usar WHERE, JOINSo HAVING?
Muhammad Babar
3
Sí, use índices para columnas en las que planea usar WHERE, JOINS o HAVING. Pero también tenga en cuenta que todas las columnas de condición no requieren índices. A veces, donde la columna de condición se usa solo una vez, por lo que es posible que no necesite un índice, mientras que otra columna de condición se usa en muchas consultas, por lo que se prefiere más para indexar esa columna.
Somnath Muluk
1
La respuesta se beneficiaría de poner, "columnas a las que se hace referencia en la cláusula WHERE y columnas utilizadas en las cláusulas JOIN" en una sección TL; DR.
jpmc26
Entonces, está diciendo que si en mi WHEREcláusula estoy verificando el valor de un campo donde su columna solo puede tomar dos valores, ¿entonces debería indexar esa columna binaria? Esto parece incorrecto.
AjaxLeung
@AjaxLeung: Recuerde la máxima de Knuth "La optimización prematura es la raíz de todo mal". Puede crear índices en columnas binarias, pero debe depender de a qué costo (como insertar, tiempos de actualización). Si su lógica empresarial depende a menudo de ese conmutador binario, es posible que se requiera que la columna binaria tenga índice.
Somnath Muluk
20

Algunas personas respondieron una pregunta similar aquí: ¿Cómo sabe qué es un buen índice?

Básicamente, realmente depende de cómo consultará sus datos. Quiere un índice que identifique rápidamente un pequeño subconjunto de su conjunto de datos que sea relevante para una consulta. Si nunca consulta por fecha, no necesita un índice, incluso si es en su mayoría único. Si todo lo que hace es obtener eventos que ocurrieron en un cierto rango de fechas, definitivamente querrá uno. En la mayoría de los casos, un índice de género no tiene sentido, pero si todo lo que hace es obtener estadísticas sobre todos los hombres y, por separado, sobre todas las mujeres, podría valer la pena crear uno. Averigüe cuáles serán sus patrones de consulta y acceda a qué parámetro reduce más el espacio de búsqueda, y ese es su mejor índice.

También considere el tipo de índice que crea: los árboles B son buenos para la mayoría de las cosas y permiten consultas de rango, pero los índices hash lo llevan directamente al grano (pero no permiten rangos). Otros tipos de índices tienen otros pros y contras.

¡Buena suerte!

SquareCog
fuente
9

Todo depende de las consultas que espere hacer sobre las tablas. Si solicita todas las filas con un cierto valor para la columna X, tendrá que hacer un escaneo completo de la tabla si no se puede usar un índice.

Los índices serán útiles si:

  • La columna o columnas tienen un alto grado de singularidad.
  • Con frecuencia, debe buscar un determinado valor o rango de valores para la columna.

No serán útiles si:

  • Está seleccionando un gran% (> 10-20%) de las filas de la tabla
  • El uso de espacio adicional es un problema
  • Quiere maximizar el rendimiento de la plaquita. Cada índice de una tabla reduce el rendimiento de la inserción y actualización porque deben actualizarse cada vez que cambian los datos.

Las columnas de clave principal suelen ser excelentes para la indexación porque son únicas y, a menudo, se utilizan para buscar filas.

Yeso
fuente
Las búsquedas de cadenas donde el valor puede estar en cualquier lugar dentro de la cadena pueden hacer que no use esos índices en ese caso.
Arthur Thomas
5

En general (no uso mssql, por lo que no puedo comentar específicamente), las claves primarias hacen buenos índices. Son únicos y deben tener un valor especificado. (Además, las claves primarias hacen índices tan buenos que normalmente tienen un índice creado automáticamente).

Un índice es efectivamente una copia de la columna que se ha ordenado para permitir la búsqueda binaria (que es mucho más rápida que la búsqueda lineal). Los sistemas de bases de datos pueden utilizar varios trucos para acelerar la búsqueda aún más, especialmente si los datos son más complejos que un simple número.

Mi sugerencia sería no utilizar ningún índice inicialmente y perfilar sus consultas. Si una consulta en particular (como la búsqueda de personas por apellido, por ejemplo) se ejecuta con mucha frecuencia, intente crear un índice sobre los atributos relevantes y el perfil nuevamente. Si hay una notable aceleración en las consultas y una desaceleración insignificante en las inserciones y actualizaciones, mantenga el índice.

(Disculpas si estoy repitiendo las cosas mencionadas en tu otra pregunta, no las había visto antes).

Zooba
fuente
5

Cualquier columna que se vaya a utilizar regularmente para extraer datos de la tabla debe indexarse.

Esto incluye: claves externas -

select * from tblOrder where status_id=:v_outstanding

campos descriptivos -

select * from tblCust where Surname like "O'Brian%"

No es necesario que las columnas sean únicas. De hecho, puede obtener un rendimiento realmente bueno de un índice binario al buscar excepciones.

select * from tblOrder where paidYN='N'
pappes
fuente
Su mención explícita de las claves externas realmente me aclaró las cosas considerando las uniones.
pfabri
3

Realmente depende de tus consultas. Por ejemplo, si casi solo escribe en una tabla, lo mejor es no tener índices, simplemente ralentizan las escrituras y nunca se acostumbran. Cualquier columna que esté utilizando para unirse a otra tabla es un buen candidato para un índice.

Además, lea sobre la función de índices perdidos. Supervisa las consultas reales que se utilizan en su base de datos y puede decirle qué índices habrían mejorado el rendimiento.

jwanagel
fuente
3

Una columna GUID no es la mejor candidata para la indexación. Los índices se adaptan mejor a las columnas con un tipo de datos al que se les puede dar algún orden significativo, es decir, ordenados (entero, fecha, etc.).

No importa si los datos de una columna aumentan en general. Si crea un índice en la columna, el índice creará su propia estructura de datos que simplemente hará referencia a los elementos reales en su tabla sin preocuparse por el orden almacenado (un índice no agrupado). Entonces, por ejemplo, se puede realizar una búsqueda binaria sobre su estructura de datos de índice para proporcionar una recuperación rápida.

También es posible crear un "índice agrupado" que reordenará físicamente sus datos. Sin embargo, solo puede tener uno de estos por tabla, mientras que puede tener varios índices no agrupados.

Ceniza
fuente
Bueno, eso no es totalmente exacto de esa manera. Puede crear fácilmente un índice regular no agrupado en una columna GUID, ¿por qué no? El GUID tiene un gran inconveniente si lo usa como la clave de agrupamiento (por ejemplo, para el ÍNDICE CLÚSTER), entonces es un desastre de usar.
marc_s
1

La vieja regla general eran las columnas que se usan mucho en las cláusulas WHERE, ORDER BY y GROUP BY, o cualquiera que pareciera usarse en las combinaciones con frecuencia. Tenga en cuenta que me refiero a índices, NO a clave principal

No para dar una respuesta 'vainilla', pero realmente depende de cómo acceda a los datos

curtisk
fuente
1

Su clave principal siempre debe ser un índice. (De hecho, me sorprendería que MS SQL no lo indexara automáticamente). También debería indexar las columnas usted SELECTo ORDERpor con frecuencia; su propósito es tanto la búsqueda rápida de un valor único como la clasificación más rápida.

El único peligro real al indexar toomuchas columnas es ralentizar los cambios en las filas en tablas grandes, ya que todos los índices también deben actualizarse. Si realmente no está seguro de qué indexar, simplemente programe sus consultas más lentas, observe qué columnas se utilizan con más frecuencia e indexelas. Luego vea cuánto más rápido son.

Eevee
fuente
1

Los tipos de datos numéricos que están ordenados en orden ascendente o descendente son buenos índices por múltiples razones. Primero, los números son generalmente más rápidos de evaluar que las cadenas (varchar, char, nvarchar, etc.). En segundo lugar, si sus valores no están ordenados, es posible que las filas y / o páginas deban barajarse para actualizar su índice. Eso es sobrecarga adicional.

Si está utilizando SQL Server 2005 y está configurado para usar identificadores únicos (guids), y NO necesita que sean de naturaleza aleatoria, consulte el tipo de identificador único secuencial.

Por último, si habla de índices agrupados, se refiere al tipo de datos físicos. Si tiene una cadena como índice agrupado, eso podría ponerse feo.

Ian Suttle
fuente
0

Debería ser incluso más rápido si está utilizando un GUID. Suponga que tiene los registros

  1. 100
  2. 200
  3. 3000
  4. ....

Si tiene un índice (búsqueda binaria, puede encontrar la ubicación física del registro que está buscando en O (lg n) tiempo, en lugar de buscar secuencialmente O (n) tiempo. Esto se debe a que no sabe qué registros tiene en tu mesa.

Milhous
fuente
0

El mejor índice depende del contenido de la tabla y de lo que esté intentando lograr.

Tomado un ejemplo Una base de datos de miembros con una clave principal del número de seguro social de los miembros. Elegimos SS porque la aplicación prioritaria se refiere al individuo de esta manera, pero también desea crear una función de búsqueda que utilice el nombre y apellido de los miembros. Luego, sugeriría crear un índice sobre esos dos campos.

Primero debe averiguar qué datos consultará y luego determinar qué datos necesita indexar.

Joseph
fuente