En uno de mis empleadores, trabajamos en una API REST (pero también se aplica a SOAP). El cliente, que es la interfaz de usuario de la aplicación, realizaría llamadas a través de la web (LAN en implementaciones de producción típicas) a la API. La API haría llamadas a la base de datos.
Un tema que se repite en nuestras discusiones es el rendimiento: algunas personas en el equipo creen que no debería tener múltiples llamadas a la base de datos (generalmente lecturas) de una sola llamada API debido al rendimiento; debe optimizarlos para que cada llamada a la API tenga (exactamente) una llamada a la base de datos.
¿Pero es eso realmente importante? Tenga en cuenta que la IU debe realizar una llamada de red a la API; eso es bastante grande (orden de magnitud de milisegundos). Las bases de datos están optimizadas para mantener las cosas en la memoria y ejecutar lecturas muy, muy rápidamente (por ejemplo, SQL Server carga y mantiene todo en RAM y consume casi toda su RAM libre si puede).
TLDR: ¿Es realmente importante preocuparse por las llamadas a múltiples bases de datos cuando ya estamos haciendo una llamada de red a través de LAN? Si es así, ¿por qué?
Para ser claros, estoy hablando del orden de magnitud: sé que depende de detalles (hardware de la máquina, elección de API y DB, etc.). Si tengo una llamada que toma O (milisegundos), ¿se optimiza para DB? llamadas que toman un orden de magnitud menos, ¿realmente importan? ¿O hay más en el problema que esto?
Editar: para la posteridad, creo que es bastante ridículo hacer afirmaciones de que necesitamos mejorar el rendimiento combinando llamadas a la base de datos en estas circunstancias, especialmente con la falta de perfiles. Sin embargo, no es mi decisión si hacemos esto o no; Quiero saber cuál es la razón detrás de pensar que esta es una forma correcta de optimizar las llamadas a la API web.
fuente
Respuestas:
La lógica
En teoría, tienes razón. Sin embargo, hay algunos defectos con esta justificación:
Por lo que dijo, no está claro si realmente probó / perfiló su aplicación. En otras palabras, ¿ sabe realmente que las transferencias de red desde la aplicación a la API son el componente más lento? Como eso es intuitivo, es fácil suponer que lo es. Sin embargo, cuando se habla de rendimiento, nunca debe suponer. En mi empleador, soy el líder de rendimiento. Cuando me uní por primera vez, la gente seguía hablando de CDN, replicación, etc., basada en la intuición sobre cuáles deben ser los cuellos de botella. Resulta que nuestros mayores problemas de rendimiento fueron consultas de bases de datos de bajo rendimiento.
Está diciendo que debido a que las bases de datos son buenas para recuperar datos, que la base de datos se ejecuta necesariamente al máximo rendimiento, se está utilizando de manera óptima y no hay nada que se pueda hacer para mejorarla. En otras palabras, las bases de datos están diseñadas para ser rápidas, por lo que nunca debería tener que preocuparme por eso. Otra peligrosa línea de pensamiento. Es como decir que un automóvil debe moverse rápidamente, por lo que no necesito cambiar el aceite.
Esta forma de pensar supone un proceso único a la vez, o dicho de otra manera, sin concurrencia. Se supone que una solicitud no puede influir en el rendimiento de otra solicitud. Se comparten recursos, como E / S de disco, ancho de banda de red, agrupaciones de conexiones, memoria, ciclos de CPU, etc. Por lo tanto, reducir el uso de un recurso compartido por una llamada de la base de datos puede evitar que otras solicitudes se ralenticen. Cuando me uní a mi empleador actual por primera vez, la gerencia creía que ajustar una consulta de base de datos de 3 segundos era una pérdida de tiempo. 3 segundos es tan poco, ¿por qué perder el tiempo? ¿No estaríamos mejor con un CDN o compresión u otra cosa? Pero si puedo ejecutar una consulta de 3 segundos en 1 segundo, digamos agregando un índice, eso es 2/3 menos de bloqueo, 2/3 menos tiempo dedicado a ocupar un hilo y, lo que es más importante, menos datos leídos del disco,
La teoría
Existe una concepción común de que el rendimiento del software se trata simplemente de velocidad .
Desde una perspectiva puramente rápida, tienes razón. Un sistema es tan rápido como su componente más lento. Si ha perfilado su código y descubrió que Internet es el componente más lento, entonces todo lo demás obviamente no es la parte más lenta.
Sin embargo, dado lo anterior, espero que pueda ver cómo la contención de recursos, la falta de indexación, el código mal escrito, etc. pueden crear diferencias sorprendentes en el rendimiento.
Los supuestos
Una última cosa. Usted mencionó que una llamada a la base de datos debería ser barata en comparación con una llamada de red desde la aplicación a la API. Pero también mencionó que la aplicación y los servidores API están en la misma LAN. Por lo tanto, ¿no son ambos comparables como llamadas de red? En otras palabras, ¿por qué supone que la transferencia de API es un orden de magnitud más lento que la transferencia de la base de datos cuando ambos tienen el mismo ancho de banda disponible? Por supuesto, los protocolos y las estructuras de datos son diferentes, entiendo eso, pero disputo la suposición de que son órdenes de magnitud diferentes.
Donde se pone murkey
Toda esta pregunta es sobre llamadas de base de datos "múltiples" versus "únicas". Pero no está claro cuántos son múltiples. Debido a lo que dije anteriormente, como regla general, recomiendo hacer tan pocas llamadas a la base de datos como sea necesario. Pero eso es solo una regla general.
Aquí es por qué:
TL; DR
Sí, pero solo hasta cierto punto. Debe intentar minimizar el número de llamadas a la base de datos cuando sea práctico, pero no combine las llamadas que no tienen nada que ver entre sí solo por el hecho de combinarlas. Además, evite llamar a la base de datos en un bucle a toda costa.
fuente
Parece que su equipo está optimizando antes de tener una razón para hacerlo. ¿Ha medido el tiempo para ejecutar estas solicitudes? Es probable que este paradigma cree un peor rendimiento para el usuario final ya que los viajes de ida y vuelta al servidor web tendrán una latencia mucho mayor que el tiempo de conexión del servidor web a la base de datos. Además de eso, la mayoría de los navegadores web solo harán 2 conexiones simultáneas a un solo servidor web, por lo que para páginas complejas es probable que encuentres un cuello de botella allí.
De cualquier manera, las decisiones de optimización no deben tomarse sin datos que lo respalden. Mídalo y descubra qué es lo mejor para su aplicación.
fuente
No podemos decirte
No sabemos cómo son sus consultas. No sabemos cuánto tardan en completarse. No sabemos cuántos gastos generales implica cada solicitud a su servidor API. No sabemos cuán geográficamente dispersos están sus clientes. Etc.
Si este es un escenario que requiere optimización y es uno en el que puede decidir si dividir o unir las llamadas, debe compararlo en ambos sentidos : decidir para qué está optimizando (latencia de la interfaz de usuario, carga de CPU del servidor, contención, etc.) y elija el que mejor logre su objetivo de optimización.
Aparte de eso, la única una cosa que puedo añadir con relativa certeza es la siguiente:
Dentro de una sola solicitud, debe realizar todas las consultas que necesita realizar para generar una respuesta.
En otras palabras, si la respuesta no se puede generar hasta que se realicen todas las N consultas, generalmente no tiene sentido separarlas. Si puede generar resultados significativos, ya sean intermedios o completos, después de cada consulta, comience la evaluación comparativa.
fuente
Dos pensamientos:
Primero, para el consumidor que usa la API, está haciendo una llamada para realizar una tarea. Lo que sucede después de que su servidor recibe la llamada para completar la solicitud no debe ser tan rígido. Si esa llamada de un consumidor requiere 10 elementos de subtrabajo para reunir los datos y devolverlos, entonces eso debería ser aceptable.
Segundo: ¿Ve un problema real de rendimiento de la base de datos con el proceso en cuestión? Mi experiencia ha demostrado que, a menudo, tratar de poner todos los aspectos de una solicitud de base de datos en una sola llamada puede resultar en una llamada menos eficiente que simplemente hacer tres o cuatro llamadas de datos. Las bases de datos modernas son muy eficientes en los planes de caché y ejecución. A menudo, cuando intentas hacer demasiado, verás procedimientos con cursores (muy malo para el rendimiento porque los datos se actúan fila por fila, no como un conjunto a la vez) y un código que resulta en un plan menos eficiente que si hubieras roto la llamada en varios pequeños pasos fáciles.
Por simple organización del código, estoy de acuerdo en que cada llamada a la API posiblemente deba llamar a un único procedimiento almacenado (o función db) que a su vez es responsable de completar la solicitud. Puede haber más de un paso en el procedimiento.
fuente
SELECT
s.Si la base de datos está en un servidor diferente al servicio REST, cada llamada a la base de datos dará como resultado un viaje de ida y vuelta en la red y eso puede afectar significativamente el rendimiento:
Una vez observé que una sola llamada de servicio web se traducía en aproximadamente 500 consultas de la base de datos; esto no era un problema cuando tanto el servicio web como la base de datos se encuentran en la misma máquina, pero se convirtió en un tiempo de respuesta de 6-7 segundos cuando estaban en diferentes máquinas.
Obviamente, 500 viajes de ida y vuelta a la base de datos es bastante extremo. No estoy seguro de cuáles son sus requisitos de rendimiento, pero como regla general, diría que si se queda con alrededor de 10 consultas de base de datos por llamada REST, no debería experimentar un impacto significativo en el rendimiento.
fuente
Tenemos un par de aplicaciones que son muy, muy conversadoras. Hay una llamada a la base de datos para cada. Soltero. Pequeño. Cosa. Servir datos de referencia una y otra y otra vez es una parte importante de la carga de trabajo en el sistema. Toda esa programación de subprocesos de trabajo, adquisición y caída de bloqueos, planificación de comprobación de caché, etc., se suma incluso si no hay una E / S de disco real. La contención es mayor porque las transacciones tienen que mantener bloqueos en múltiples llamadas a la base de datos y, por lo tanto, el rendimiento es mucho menor de lo que podría ser. Esos equipos ahora están considerando tener que comprar servidores de bases de datos nuevos y muy caros debido a esto.
Por lo tanto, aunque la mayor parte del tiempo transcurrido en la configuración actual de su sistema se toma con llamadas REST API, ignorar el rendimiento en el nivel de base de datos es almacenar problemas para el futuro.
fuente
La ruta de optimización presentada es simplemente la forma incorrecta de ver las cosas.
Las llamadas a la API deben ser atómicas. En otras palabras, debería poder hacer 1 llamada a la API web para realizar la acción que quiero. Ya sea para obtener datos, actualizar un registro o lo que sea. NUNCA debe tomar más de 1 llamada para provocar la acción. E intentar aprovechar las transacciones a través de múltiples llamadas debe evitarse como la peste.
A veces una sola acción es bastante compleja. Por ejemplo, obtener datos que se combinan de varias fuentes: nuevamente, esto debería ser una sola llamada. O todo funciona o falla todo.
Ahora, decir que una sola llamada a la API solo debe ejecutar una consulta DB es un poco tonto. Como ha señalado, la sobrecarga para ordenar la llamada a través de la red suele ser mucho más costosa en términos de tiempo total.
De alguna manera puedo entender su afirmación de que una sola consulta se ejecuta más rápido que varias; pero esto da una falsa impresión ya que ignora la DB total y la carga de la red. Solo al perfilar las diversas formas de extraer datos de la base de datos puede descubrir cuál es realmente el problema. Estoy seguro de que todos tienen una historia en la que una consulta en particular ejecutada 100 veces más de lo esperado mató el sistema hasta que se estableció un índice adecuado ...
En última instancia, no podrás convencerlos con solo hablar. Configure un caso de prueba para ambos enfoques y perfílelos. Preste atención al tiempo total para adquirir los datos que necesita, la cantidad de tráfico de red generado, el número y el momento de las llamadas a la base de datos, etc. Adopte un enfoque holístico, lo que significa que mira todo el sistema, y debería terminar con un montón de datos para comer cuervo o mostrarles el camino dorado.
fuente