¿Es una optimización prematura agregar índices de base de datos?

61

Un colega mío sugirió que revisemos todas las consultas en nuestra aplicación y que agreguemos índices en consecuencia.

Siento que esta es una optimización prematura porque nuestra aplicación aún no se ha lanzado. Sugerí monitorear las consultas lentas una vez que entremos en vivo y luego agregar índices en consecuencia.

¿Cuál es el consenso general al diseñar su base de datos, debe agregar un índice coincidente cada vez que escribe una nueva consulta? ¿O es mejor simplemente monitorear y ver cómo va?

Marco de Jongh
fuente
32
Puede ser una cuestión de opinión, sin embargo, creo que algunos índices podrían agregarse a priori.
Basile Starynkevitch
2
@BasileStarynkevitch Totalmente de acuerdo en que ya tenemos índices clave principales y las obras. ¿Pero dónde trazas la línea?
Marco de Jongh
1
Mis dos centavos de experiencia: estaba probando algunas de mis primeras consultas de búsqueda en un subconjunto de nuestra base de datos. Las pruebas que realicé estaban totalmente bien en mi copia local. Luego empujé la aplicación al área de preparación que aloja la base de datos completa. Mis pruebas se ejecutaron en <500 ms , mientras que el sistema de preparación tardó varios minutos en resolverse. Mi jefe estaba completamente confundido sobre por qué la aplicación no se estaba cargando. Explique que las operaciones de tipo son su amigo ... ¡Al menos busque escaneos secuenciales en tablas grandes, por lo menos!
Chris Cirefice
2
No agregar índices es como usar bubbleort. La mayoría de las veces no encontrará ningún problema cuando lo pruebe, pero una vez que su programa comience a aumentar en vivo, se encontrará con muchos problemas. Y los índices pueden hacer fácilmente un factor 100 en la diferencia de velocidad.
Pieter B
3
Solo recuerda siempre: un índice no es una cosa mágica que acelerará tus consultas. Un índice aumentará el costo en la mayoría de las operaciones DML y, dependiendo del tipo, puede generar mucha espera cuando muchas personas actualizan la misma tabla. Para consultas: hay muchas consultas que no se benefician en absoluto de un índice, donde un FTS es el más rápido o donde Particionamiento hace todo el trabajo por usted. - ¡Solo agregue el índice donde SABE que serán beneficiosos!
Falco

Respuestas:

132

La optimización prematura es "optimizar" algo debido a una sensación vaga e intuitiva de que, ya sabes, esto probablemente será lento, especialmente en detrimento de la legibilidad y facilidad de mantenimiento del código . No significa intencionalmente no seguir buenas prácticas bien establecidas con respecto al rendimiento.

A veces es una línea difícil de trazar, pero definitivamente diría que no agregar ningún índice antes de que salga en vivo es una optimización demasiado tardía ; esto castigará a los primeros usuarios, sus usuarios más ansiosos e importantes, y les dará una visión negativa de su producto, que luego difundirán en revisiones, discusiones, etc. buena idea, pero me aseguraría de hacerlo antes de la versión beta.

Mason Wheeler
fuente
11
Sí, debe hacerse en la fase de prueba de carga
Alvaro
152
Optimizar antes de saber dónde están las partes lentas es una optimización prematura. ¡Liberar la cosa antes de saber dónde están las partes lentas es una liberación prematura !
MathematicalOrchid
44
@MathematicalOrchid: ¡Esa es una frase genial! ¿Me lo prestas en otro lado?
Pieter Geerkens
3
@PieterGeerkens ¡Claro, noquea! ;-) Estoy triste de que más de 91 votos a favor no me den ninguna reputación ... je.
MathematicalOrchid
3
@MathematicalOrchid debería haber sido una respuesta. Podría funcionar para obtener la respuesta "más pequeña, directa al punto".
Mindwin
48

supervise las consultas lentas una vez que salgamos al mercado

¡porque nada dice calidad como hacer sufrir a sus usuarios por falta de diseño!

Debe saber qué consultas necesitan índices cuando diseña las tablas, sabe qué columnas se consultan en dónde se unen las cláusulas y las uniones. Estos ya deberían estar indexados porque lo que podría no ser aparente en un entorno en vivo puede volverse evidente rápidamente cuando aumenta la carga o los datos almacenados. Lo que no quiere hacer cuando esto sucede es colocar índices en cada consulta 'lenta', terminará con un índice en todo.

gbjbaanb
fuente
10
Derecha. Considere los índices como parte del diseño de la base de datos. Use índices para evitar un escaneo completo de la tabla para cualquier consulta que el usuario final comúnmente realizará en tiempo real.
AE
1
@DocBrown No estoy tan seguro, cuando diseñas una tabla tienes (o debes tener) algo de comprensión de cómo se va a usar. Se consultará una tabla de persona por ID, o posiblemente por apellido. Si alguien comienza a acceder a través de DoB, dirección o número de teléfono, entonces agregará índices para cada campo, ¿y dónde termina eso?
gbjbaanb
44
@gbjbaanb: finaliza cuando las personas dejan de agregar funciones al producto, lo que podría ser "nunca" dependiendo de su metodología.
Steve Jessop
1
@SteveJessop Quiero decir que indexas de acuerdo con las columnas principales a las que deseas acceder. Para una tabla de personas, es posible que tenga una función de búsqueda (si olvida su nombre de usuario, puede buscar en el correo electrónico, por ejemplo), pero luego siempre usa la ID. Entonces ID es el único que necesita indexación. Si realiza muchas búsquedas en otros campos, es posible que desee un índice, esto saldrá a tiempo, pero generalmente no desea indexar cada columna solo porque alguien alguna vez decidió escribir una consulta no estándar, pero puede utilizar un mecanismo diferente para estos casos "únicos".
gbjbaanb
2
@gbjbaanb: claro, las personas no deberían buscar repetidamente el mismo apellido en una tabla debido a que es un identificador marginalmente más conveniente para ellos que la clave adecuada para la tabla. Yo diría que ese es el caso si la tabla está indexada por apellido o no, de hecho, ya que hay algo muy sospechoso en un tramo de código que supone que todo está operando en "el mismo usuario", pero no puede expresarlo. en código recordando la ID :-) Estaba imaginando casos en los que no se anticipaba la necesidad de una búsqueda inversa hasta que el cliente lo mencionara ...
Steve Jessop
26

La "optimización prematura", en su sentido despectivo, significa una optimización costosa que podría no ser necesaria. ¡ No significa toda la optimización implementada antes del último punto posible para evitar la bancarrota!

En particular, es legítimo optimizar en función de las pruebas de rendimiento antes de ponerlo en funcionamiento, para garantizar que pueda cumplir con algunos requisitos razonables (aunque aproximados) para que su aplicación no funcione completamente.

Como mínimo absoluto , debe cargar su base de datos con una cantidad plausible de datos de prueba y verificar la capacidad de respuesta de su aplicación. Esto no es prematuro, ya que sabe que va a suceder, y detectará cualquier consulta que provoque escaneos absurdamente lentos. Como AE dice en un comentario:

Use índices para evitar un escaneo completo de la tabla para cualquier consulta que el usuario final comúnmente realizará en tiempo real

Al menos, para las tablas que están planificadas para crecer en uso.

Luego, como acceso directo a eso, si tiene una experiencia significativa con el motor de base de datos y ya ha planificado las pruebas cuando escribe el primer corte del código, entonces a menudo sabrá sin ejecutarlo que la consulta está la escritura será demasiado lenta sin un índice. Por supuesto, puede fingir que no sabe y ver la prueba fallar antes de agregar el índice para que pase, pero no hay razón para que el código defectuoso conocido (porque no responde) se active.

Steve Jessop
fuente
20

Siento que esta es una optimización prematura porque nuestra aplicación aún no se ha lanzado. Sugerí monitorear las consultas lentas una vez que entremos en vivo y luego agregar índices en consecuencia.

No puede tratar a sus usuarios finales y entorno de producción como garantía de calidad. En otras palabras, estás diciendo que lo resolverás en producción. No creo que sea el camino correcto, y veo que ese enfoque sale terriblemente mal todos los días .

Debe tener una cosa en mente, ya que no puede pintar esto con un pincel ancho.

¿Cuál es su carga de trabajo común ?

Eso puede sonar obvio o aburrido, pero es significativo en la práctica. Si tiene 10 consultas que representan el 98% de su carga de trabajo (bastante común, créalo o no), mi recomendación sería un análisis difícil antes de la producción . Con datos realistas y representativos, asegúrese de que esas 10 consultas sean tan buenas como sea posible ( perfecto es una pérdida de tiempo valioso y casi no se puede lograr).

Para las otras 200 consultas que conforman el 2% de la carga de trabajo , esas son las que probablemente no valgan la pena, y compensarán las rarezas de solución de problemas de rendimiento de esquina en la producción. Eso también es una realidad, y no es una cosa terriblemente mala. Pero eso no significa ignorar las mejores prácticas de indexación o hacer suposiciones estimadas sobre la recuperación de datos.

Es común y una buena práctica averiguar el rendimiento de la base de datos antes de la producción. De hecho, hay una posición relativamente común para este tipo de cosas llamada DBA de desarrollo .

Pero...

Algunos llevan eso demasiado lejos y se vuelven locos agregando índices "por si acaso". Alguien recomienda que este sea un índice faltante? Agréguelo y otras cuatro variaciones. También una mala idea. No solo debe pensar en la recuperación de sus datos, sino en la modificación de datos. Cuantos más índices tenga en una tabla, en general, más sobrecarga tendrá cuando modifique los datos.

Como la mayoría de las cosas, hay un equilibrio saludable.

Como una pequeña nota al margen divertida ... La pluralización de "Índice"

Los "índices" son para personas financieras

Los "índices" son para nosotros

Thomas Stringer
fuente
2
Esto necesita más votos. No podría estar mas de acuerdo.
RubberDuck
+1 para el bit "por si acaso" (eso sería una optimización prematura). Si pudiera, volvería a votar por el bit de "carga de trabajo común".
David
Esperemos que sepa de antemano qué 10 consultas pertenecen al 98% y cuáles no.
Paŭlo Ebermann
@ PaŭloEbermann La mayoría de los DBMS tienen la capacidad de capturar esa información de manera rápida y fácil. En este caso, no hay excusa para no saber.
Thomas Stringer
@ThomasStringer Por supuesto, esto solo funciona si sus casos de prueba antes de pasar a producción están de alguna manera relacionados con lo que hacen los usuarios reales en producción.
Paŭlo Ebermann
4

No, no es una optimización prematura, pero debe hacerse correctamente como debería ser cualquier optimización.

Esto es lo que haría:

  1. Cargue la base de datos con suficientes datos de prueba para imitar una carga de producción. No puede obtener esta precisión al 100%, pero está bien: simplemente ingrese suficientes datos. ¿Tiene una tabla una cantidad fija de datos? Cárgalo. ¿Tiene una tabla que contenga muchos datos, por ejemplo, cualquier tabla que contenga preguntas en este sitio? Cargue unos pocos millones de registros aunque solo sean datos ficticios.
  2. Active la creación de perfiles en su servidor de base de datos.
  3. Aproveche la aplicación utilizando una combinación de scripts automatizados (proporciona volumen) y usuarios reales (saben cómo romper cosas).
  4. Revise los datos de perfil. ¿Las consultas específicas son lentas? Verifique los planes de explicación y vea si el servidor de la base de datos le dice que quiere un índice pero que no existe.

Los servidores de bases de datos son piezas de software complejas e inteligentes. Pueden decirle cómo optimizarlos si sabe escuchar.

Las claves son medir el rendimiento antes y después de la optimización y dejar que la base de datos le diga lo que necesita .


fuente
3

Seguir patrones probados para problemas conocidos (como encontrar un registro por su ID) no es nada prematuro. Es solo sensato.

Dicho esto, los índices no siempre son un negocio sencillo. A menudo es difícil saber durante la fase de diseño de qué índices dependerá su tráfico y cuáles obstruirán las operaciones de escritura. Por lo tanto, argumentaría a favor de aprovechar algunas de las mejores prácticas de diseño de esquemas "obvias" (use las PK adecuadas para los patrones de lectura / escritura diseñados e indexe los FK); pero, no ponga un índice en nada más hasta que sus pruebas de estrés lo exijan.

svidgen
fuente
Pasar 30 segundos adicionales para hacer algo que es casi seguro que mejorará el rendimiento y es muy poco probable que perjudique no es la "optimización prematura". Si el 90% de las operaciones en una tabla usa una columna en particular como clave, entonces indexarla mejorará el rendimiento o el rendimiento nunca será lo suficientemente lento como para importar, y agregar código para crear el índice puede tomar menos tiempo que determinar si es realmente necesario.
supercat
@supercat "nunca" ... Hasta que empiece a ver puntos muertos en su entorno de producción ...
svidgen
¿Qué tipo de escenarios realistas imagina que serían consistentes con el 90% de las operaciones utilizando una columna como clave, y donde agregar un índice causaría un punto muerto?
supercat
@supercat No estoy seguro de entender completamente tu búsqueda. En términos de una aplicación activa, casi cualquier aumento en el tiempo de ejecución o el número de ios tiene el potencial de introducir puntos muertos. ... Pero, más concretamente, la presencia o ausencia de un índice en la mayoría de las aplicaciones es insignificante hasta que la base de datos alcanza un tamaño crítico y / o un nivel de concurrencia. Por ejemplo, cuando todos sus índices ya no caben en la memoria ...
svidgen
1
El punto es que es difícil saber cuál es la composición de su consulta hasta que los casos de uso típicos se ejecuten a través de una prueba de estrés (o hasta que vea problemas con el comportamiento inesperado del usuario en la producción). Si tiene una página que se apaga de tablex.fieldy, pero solo se golpea una vez por cada mil inserciones ... El índice puede provocar una degradación neta.
svidgen
2

Cuando se lanza su aplicación, es demasiado tarde.

Pero cualquier proceso de desarrollo adecuado debe incluir pruebas de rendimiento.

Use los resultados de sus pruebas de desempeño para decidir qué índices agregar y verifique su efectividad repitiendo las pruebas de desempeño.

Philipp
fuente
Cuando se lanza una aplicación, es realmente un buen momento para modificar los índices. Mire este sitio, stachexchange, puede apostar que los índices han cambiado mucho tiempo después de que se lanzó.
LosManos
@LosManos: Nadie paga por usar Stack Exchange.
ligereza compite con Mónica
@LightnessRacesinOrbit: por el contrario, los anunciantes pagan por usar Stack Exchange.
@ JonofAllTrades: No les importa si tenemos unas pocas horas de bajo rendimiento debido a la falta de un índice. Mi punto es que un sitio web grande, gratuito y orientado a la comunidad con un ciclo de distribución perpetuo es muy diferente de un producto comercial autónomo que se lanza periódicamente. Por lo tanto, SE no es un buen ejemplo.
ligereza compite con Mónica
1

Aunque no creo que todas las consultas deban optimizarse, los índices son una parte tan importante de RDBMS que deben considerarse antes de su publicación. Cuando ejecuta una consulta, a diferencia de otras formas de programación, no le está diciendo al sistema cómo ejecutarla. Desarrollan planes propios y casi siempre lo basan en la disponibilidad de un índice. La composición y el volumen de datos también se considerarán en momentos posteriores.

Aquí hay algunas cosas que consideraría:

  1. Hay algunas consultas que debe identificar en su desarrollo inicial que solo sabe que se usarán con frecuencia. Concéntrate en ellos.
  2. Habrá consultas lentas. Al indexarlos primero, puede determinar si el rendimiento aún no es lo suficientemente rápido y luego considerar un rediseño (la desnormalización puede ser prematura). Prefiero hacer esto antes de un lanzamiento. Nadie quiere un sistema en el que se tarden 10 minutos en encontrar algo en el inventario.
  3. Los índices pueden mejorar el rendimiento de las consultas, pero no deben obstaculizar la modificación de datos.
  4. Muchos sistemas tienen herramientas para analizar sus consultas, así que no tenga miedo de usarlas.

Después de su revisión inicial, debe hacer un seguimiento con algunas consideraciones sobre cuándo debe revisar esto nuevamente y cómo podrá recopilar la información para hacer esto (monitorear el uso, obtener copias de los datos del cliente, etc.).

Me doy cuenta de que no desea optimizar prematuramente, pero es casi seguro que tendrá un bajo rendimiento sin indexar su base de datos. Al eliminar esto, puede determinar si hay otras áreas que causan problemas de rendimiento.

JeffO
fuente
0

También depende de cuántos usuarios esperes. Definitivamente, debe hacer algunas pruebas de carga y asegurarse de que su base de datos pueda mantenerse al día con 10s a 100s a 1000s de solicitudes simultáneas. Nuevamente, depende de cuánto tráfico espere y qué áreas espera que se usen más que otras.

En general, afinaría las áreas que espero que el usuario golpee primero. Luego, afinaría todo lo que sea lento desde el punto de vista de la experiencia del usuario. Cada vez que el usuario tiene que esperar algo, obtiene una mala experiencia y puede ser rechazado. ¡No está bien!

harsimranb
fuente
0

Es una buena práctica identificar qué columnas definitivamente necesitan un índice mediante algún análisis inicial. Existe un riesgo real de degradación gradual o inesperada del rendimiento en la producción a medida que aumenta el tamaño de la base de datos si no tiene absolutamente ningún índice. La situación que desea evitar es cuando una consulta comúnmente ejecutada requiere escanear una gran cantidad de filas de la tabla. No es una optimización prematura agregar índices a las columnas críticas ya que tiene mucha de la información necesaria disponible y las posibles diferencias de rendimiento son significativas (órdenes de magnitud). También hay situaciones en las que el beneficio de los índices es menos claro o más dependiente de los datos; probablemente puede diferir la decisión de algunos de estos casos.

Algunas preguntas que debe hacer son:

  • ¿Cuáles son los límites de diseño para el tamaño de cada tabla?

Si las tablas siempre serán pequeñas (digamos <100 filas), no es un desastre si la base de datos tiene que escanear toda la tabla. Puede ser beneficioso agregar un índice, pero esto requiere un poco más de experiencia o medición para determinar.

  • ¿Con qué frecuencia se ejecutará cada consulta y cuál es el tiempo de respuesta requerido?

Si la consulta se ejecuta con poca frecuencia y no tiene requisitos estrictos de tiempo de respuesta (por ejemplo, generación de informes) y el número de filas no es enorme, entonces probablemente sea bastante seguro aplazar la adición de índices. Una vez más, la experiencia o la medición pueden ayudar a determinar si será beneficioso.

  • ¿La consulta requiere buscar en la tabla algo aparte de la clave primaria? Por ejemplo, ¿filtrar por rango de fechas, unirse a una clave externa?

Si estas consultas se ejecutan con frecuencia y tocan tablas con muchas filas, debería considerar seriamente agregar un índice de manera preventiva. Si no está seguro de si este es el caso de una consulta, puede llenar la base de datos con una cantidad realista de datos y luego mirar el plan de consulta.

usuario611910
fuente