¿Indización desde el inicio o cuando surge un problema de rendimiento?

15

Mi pregunta es sobre el uso de índices.

  1. ¿Debo comenzar a indexar desde el principio o cuando surja un problema de rendimiento?

  2. También podemos crear un índice temporal mientras ejecutamos una consulta. ¿Cuáles son los pros y los contras de tales técnicas?

codecool
fuente

Respuestas:

17

¿Debo comenzar a indexar desde el principio o cuando surja un problema de rendimiento?

La estrategia de indexación tiende a evolucionar a medida que surgen patrones de uso. Dicho esto, también hay estrategias y pautas de diseño que se pueden aplicar por adelantado.

  • Elija una buena clave de agrupación . Por lo general, puede determinar el índice agrupado apropiado en el momento del diseño, en función del patrón esperado de inserciones en una tabla. Si surge un caso convincente para un cambio en el futuro, que así sea.

  • Crea tus principales y otras restricciones únicas . Estos serán aplicados por índices únicos.

  • Cree sus claves foráneas e índices no agrupados asociados . Las claves foráneas son las columnas de unión a las que se hace referencia con mayor frecuencia, por lo que debe indexarlas desde el principio.

  • Cree índices para cualquier consulta obviamente altamente selectiva . Para los patrones de consulta que ya conoce, será altamente selectivo y probablemente usará búsquedas en lugar de escaneos.

Más allá de lo anterior, adopte un enfoque gradual y holístico para implementar nuevos índices. Por holístico, me refiero a evaluar el beneficio potencial y el impacto de todas las consultas e índices existentes al evaluar una adición.

Un problema no infrecuente en los círculos de SQL Server es la sobreindexación, como resultado de la orientación de los indicios de índice DMV y SSMS que faltan. Ninguna de estas herramientas evalúa los índices existentes y sugerirá alegremente que cree un nuevo índice de 6 columnas en lugar de agregar una sola columna a un índice de 5 columnas existente.

-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
)

-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

Kimberly Tripp tiene un excelente material sobre estrategia de indexación que si bien SQL enfocado es aplicable a otras plataformas. Para la gente de SQL Server, hay algunas herramientas útiles para identificar duplicados como el ejemplo anterior.

También podemos crear un índice temporal mientras ejecutamos una consulta. ¿Cuáles son los pros y los contras de tales técnicas?

Esto generalmente solo se aplica a consultas raramente ejecutadas, generalmente ETL. Necesitas evaluar:

  1. ¿El tiempo necesario para crear el índice reduce el tiempo de ejecución de la consulta?
  2. ¿La sobrecarga de mantenimiento de dejar el índice en su lugar supera el tiempo necesario para crear / eliminar cuando sea necesario?
Mark Storey-Smith
fuente
3
Clave de clúster +1, clave externa, clave única / primaria y no confiar en los DMV de índice que faltan al pie de la letra ... Todas estas cosas son un gran consejo. Tratar con los índices existentes, en SQL Server, es bastante fácil de monitorear usando el DMV sys.dm_db_index_usage_stats. Durante un período de tiempo, puede enumerar índices que no se han escaneado o buscado, al tiempo que observa que estos mismos índices se han actualizado varias veces. Esto es indicativo de sobreindexación.
Matt M
1
+1, sin embargo, "crea índices para cualquier consulta obviamente altamente selectiva". no cubre todos los demás escenarios. Los índices pueden ayudar a ordenar los resultados incluso si sus consultas no son muy selectivas. También pueden acelerar las consultas si cubren todas las columnas seleccionadas.
razón
1
De acuerdo, pero la pregunta era buscar un punto de partida en lugar del final del juego. Identificar consultas para cubrir es difícil sin patrones de uso, ya que rara vez puede cubrirlas todas.
Mark Storey-Smith
8

Realmente hay riesgos asociados con ambos enfoques:

Opción a) Indice desde el principio, pero no se dé cuenta de que ha creado una serie de índices que nunca se utilizan. Estos agregan algo de sobrecarga (más notablemente a las consultas que modifican los datos, pero también con la optimización de las instrucciones SELECT que intentan identificar el mejor índice).

Tendrá que disciplinarse para identificar los índices que ya no se usan e intentar eliminarlos (PostgreSQL puede hacer esto; desafortunadamente, MySQL, en comparación, es muy débil en este momento).

Opción b) No agregue índices hasta que las personas comiencen a quejarse, o sus herramientas de diagnóstico activen que ciertas consultas son lentas y podrían mejorarse.

El riesgo que presenta es que no tiene una ventana de tiempo suficientemente grande entre cuando nota que necesita el índice y cuando tiene que agregarlo.

PostgreSQL admite la creación de índices CONCURRENTLY, lo que reduce parte del estrés de este requisito de agregar un índice repentino, pero hay algunas advertencias que se mencionan en el manual.


La opción (b) tiende a ser mi preferencia, pero creo que un híbrido de ambas opciones es probablemente la mejor solución. Tiene que ver con su nivel de confianza en cuanto a si cree que realmente se utilizará un índice.

Lo que hace que esta discusión sea particularmente compleja es que, por lo general, es fácil cambiar los índices, pero es más difícil cambiar el esquema. No quiero promover la reacción tardía de b como una excusa para ser imprudente.

Morgan Tocker
fuente
4

Además de la respuesta de Mark

Puede tener una idea al tener datos de prueba realistas en las cantidades esperadas. He visto muchos, muchos (demasiados) casos en los que una consulta se ejecuta bien con 1000 filas pero no el millón en producción.

Si puede, trabaje en una copia de producción más adelante,

Por supuesto, he visto el extraño problema solo en la producción debido a los patrones de uso cuando todo lo demás es idéntico

Índices temporales? Fuera de los patrones de carga ETL, si los necesita una vez, los necesitará nuevamente. No olvide: un índice crear / soltar es una escritura y se registra = más carga

gbn
fuente
3

Solo para agregar algunas cosas.

  • Los índices temporales son una idea terrible ... a menos que el índice esté en una tabla temporal.
  • Los índices ocupan mucho más espacio de datos (así como otros gastos generales) de lo que la gente cree. Por lo tanto, créelos conservadoramente.

Este es mi enfoque.

  1. Similar a Mark, haga índices donde tengan sentido, pero no lo venza.
  2. No tiene que esperar hasta que el rendimiento sea lento para crear nuevos índices. Cada vez que escriba un nuevo SQL, ejecute un plan de consulta (preferiblemente en su base de datos prod). Debería poder ver si se requiere un nuevo índice.
  3. No tenga miedo de poner > 0o > ""en sus cláusulas where para columnas no utilizadas.

    1. Es decir, supongamos que tiene un índice en A, B, C y D. Sin embargo, solo tiene información A, B, D. No hay razón por la que no puedas ...
    select * from blah 
    where A="one" 
    and B="two" 
    and C>=""     --to match index
    and D="four"
    
    --This will use your existing index. No need to create a redundant one.
usuario606723
fuente
Otra cosa, esto está en el foro "dba", pero la creación de índices realmente debería ser responsabilidad del desarrollador, no de dba. (Para los casos en que están completamente separados.)
user606723
2
Su declaración con respecto al espacio ocupado por los índices es un poco engañosa, hay muy poca sobrecarga en un índice no agrupado. Si pudiera publicar una pregunta sobre ese punto, valdría la pena explorarlo más a fondo. En segundo lugar, no estoy de acuerdo con que la creación de índices sea del dominio del desarrollador. Es en gran medida una de las áreas donde la colaboración entre el desarrollador y el DBA puede producir los mejores resultados.
Mark Storey-Smith
1
Te daré un ejemplo de una de nuestras tablas. tamaño de la tabla: 21052404 KB. Tamaño de un índice no agrupado en esta tabla: 6637470 KB. Muy poco sobrecarga? Yo creo que no. Además, no digo que no se deba colaborar con los DBA, digo que debería ser responsabilidad del desarrollador determinar si es necesario crear un nuevo índice. No deberían escribir SQL y esperar que los dbas resuelvan esto por su cuenta.
user606723
1
No puedes citar números así sin contexto. Sin especificar las columnas de índice NC y la clave agrupada, es imposible calcular la proporción de sobrecarga frente a datos.
Mark Storey-Smith
Touche La clave es [numeric (24), char, date] y las columnas NC son [date, numeric (24)]. (Solo dos columnas en este índice en particular).
user606723
2

Trataré de responder solo la primera pregunta. Si puede estimar incluso aproximadamente desde el principio cuántos registros tendrá en sus tablas después de un cierto período de tiempo, entonces diría que es mejor comenzar desde el principio para diseñar algunos índices. Intente utilizar algunas herramientas de prueba o scripts de prueba que automatizarán tantas llamadas como sea posible para las llamadas de aplicación que cree que se usarán con mayor frecuencia y verá qué escaneos de tabla se pueden evitar desde el principio.

Al principio será un trabajo de adivinanzas, pero con el tiempo, ya que tiene estadísticas de uso adecuadas, tendrá una imagen más clara.

Mariana
fuente