Es una idea que escuché repetir en un puñado de lugares. Algunos más o menos reconocen que una vez que tratar de resolver un problema puramente en SQL excede un cierto nivel de complejidad, de hecho debería manejarlo en código.
La lógica detrás de la idea es que, para la gran mayoría de los casos, el motor de la base de datos hará un mejor trabajo para encontrar la forma más eficiente de completar su tarea de lo que podría hacer en el código. Especialmente cuando se trata de cosas como condicionar los resultados a las operaciones realizadas en los datos. Podría decirse que con los motores modernos efectivamente JIT'ing + almacenamiento en caché de la versión compilada de su consulta tendría sentido en la superficie.
La pregunta es si aprovechar o no su motor de base de datos de esta manera es una práctica de diseño inherentemente mala (y por qué). Las líneas se vuelven borrosas aún más cuando toda la lógica existe dentro de la base de datos y solo la estás golpeando a través de un ORM.
fuente
Respuestas:
En palabras simples:
Estas son cosas para las que está hecho SQL y, lo creas o no, he visto hacerlo en código:
Hacer estas cosas en lugar de confiar en SQL o RDBMS lleva a escribir toneladas de código sin valor agregado , lo que significa más código para depurar y mantener. Y supone peligrosamente que solo se podrá acceder a la base de datos a través de la aplicación.
fuente
Reformularía eso a "Nunca haga en código lo que SQL Server puede hacer por usted bien ".
Cosas como la manipulación de cadenas, el trabajo de expresiones regulares y cosas que no haría en SQL Server (salvo SQL CLR).
Lo anterior tiende a hablar sobre cosas como: uniones, operaciones de operaciones y consultas. La intención detrás de esto es delegar gran parte del trabajo pesado a SQL Server (en las cosas en las que es bueno) y reducir la cantidad de IO tanto como sea posible (así que deje que SQL haga las uniones y filtre con una
WHERE
cláusula, devolviendo mucho conjunto de datos más pequeño que de lo contrario).fuente
La clave de la respuesta es que debe buscar SQL haciendo algo bien, en lugar de simplemente hacer algo por usted. SQL es un lenguaje increíblemente poderoso. Junto con las funciones integradas, potencialmente puede hacer muchas cosas. Sin embargo, el hecho de que pueda hacer algo en SQL no debería ser una excusa para hacerlo en SQL.
Mi criterio específico para tomar una decisión es observar la cantidad de datos que recupera y la cantidad de viajes de ida y vuelta: si puede reducir la cantidad de datos enviando una tarea al servidor, sin aumentar la cantidad de datos redondos. dispara, entonces la tarea pertenece al servidor; Si la cantidad de datos permanece igual o aumenta sin una caída simultánea en el número de viajes de ida y vuelta, la tarea pertenece a su código.
Considere estos ejemplos:
fuente
WHERE
cláusula.En resumen , sería correcto decir que: "Nunca realice operaciones específicas de la base de datos en su base de código", ya que se abordan mejor en su base de datos.
Mire el ejemplo de las operaciones base establecidas . Como ya sabrá, los RDBMS están diseñados para manejar operaciones comunes de almacenamiento y manipulación de datos.
Además, la elección del proyecto de base de datos juega un papel importante . Tener un RDBMS (MS SQL, Oracle, etc.) es diferente a las bases de datos NoSQL como RavenDB.
fuente
Como regla general, su base de datos tiene más información para trabajar que su aplicación, y puede realizar operaciones de datos comunes de manera más eficiente. Su base de datos mantiene índices, por ejemplo, mientras que su aplicación tendría que indexar los resultados de la búsqueda sobre la marcha. Por lo tanto, si todo lo demás es igual, su carga de trabajo general puede reducirse empujando el trabajo a la base de datos en lugar de a la aplicación.
Pero a medida que su producto escala, generalmente se vuelve más fácil escalar su aplicación que escalar su base de datos. En instalaciones grandes, no es raro ver que los servidores de aplicaciones superen en número a los servidores de bases de datos en un factor de 10 a 1 o más. Agregar más servidores de aplicaciones a menudo es una simple cuestión de clonar un servidor existente en un nuevo hardware. Agregar nuevos servidores de bases de datos, por otro lado, es dramáticamente más difícil en la mayoría de los casos.
Entonces, en este punto, el mantra se convierte en proteger la base de datos . Resulta que al almacenar en caché los resultados de la base de datos
memcached
o al poner en cola las actualizaciones en un registro del lado de la aplicación, o al recuperar los datos una vez y calcular sus estadísticas en su aplicación, puede reducir drásticamente la carga de trabajo de su base de datos, evitando tener que recurrir a Una configuración de clúster DB aún más complicada y frágil.fuente
Creo que sería un mal diseño no utilizar la base de datos para lo que está destinada. Nunca he visto ninguna base de datos donde las reglas se aplicaran fuera de la base de datos que tuviera buenos datos. Y he mirado cientos de bases de datos.
Entonces, cosas que deben hacerse en una base de datos:
Auditoría (la auditoría solo de aplicación no rastreará todos los cambios en la base de datos y, por lo tanto, no tiene valor).
Restricciones de ingeridad de datos que incluyen valores predeterminados, restricciones de clave externa y reglas que siempre deben aplicarse a todos los datos. Todos los datos no siempre se cambian o insertan a través de una aplicación, hay correcciones de datos únicas, especialmente de grandes conjuntos de datos que no son prácticos para hacer un registro a la vez (actualice estos 100,000 registros que se marcaron incorrectamente como estado 1 cuando deberían sea 2 debido a un error en el código de la aplicación o actualice todos los registros del cliente A al cliente B porque la compañía B compró la compañía A) y las importaciones de datos y otras aplicaciones que podrían tocar la misma base de datos.
UNIÓN y filtrado de cláusulas where (para reducir la cantidad de registros enviados a través de la red)
fuente
La base de datos es exactamente eso; La capa de datos de su aplicación. Su trabajo es proporcionar a su aplicación los datos solicitados y almacenar los datos que se le proporcionan. Su aplicación es el lugar para colocar el código que realmente funciona con los datos; mostrarlo, validarlo, etc.
Si bien el sentimiento en la línea del título es admirable y preciso hasta cierto punto (el meollo del filtrado, la proyección, la agrupación, etc. , en el abrumador número de casos debería dejarse al DB), una definición de "bien" podría estar en orden. Las tareas que SQL Server puede ejecutar con un alto nivel de rendimiento son muchas, pero las tareas que puede demostrarque SQL Server hace correctamente de manera aislada y repetible son muy pocos. SQL Management Studio es un gran IDE de base de datos (especialmente teniendo en cuenta las otras opciones con las que he trabajado como TOAD), pero tiene sus limitaciones, la primera de ellas es que casi todo lo que usa (o cualquier código de procedimiento que ejecute) el DB debajo) es, por definición, un "efecto secundario" (estado alterado que se encuentra fuera del dominio del espacio de memoria de su proceso). Además, el código de procedimiento dentro de SQL Server solo ahora, con los últimos IDE y herramientas, se puede medir de la manera en que el código administrado puede usar métricas de cobertura y análisis de ruta (por lo que puede demostrar que esto es particular si la declaración se encuentra en las pruebas X , Y y Z, y la prueba X está diseñada para hacer que la condición sea verdadera y ejecutar esa mitad mientras Y y Z ejecutan el "else" . Eso, a su vez, supone que tiene una prueba que puede configurar la base de datos con un estado inicial particular, ejecutar el código de procedimiento de la base de datos a través de alguna acción y afirmar los resultados esperados.
Todo esto es mucho más difícil e involucrado que la solución provista por la mayoría de las capas de acceso a datos; suponga que la capa de datos (y, para el caso, el DAL) sabe cómo hacer su trabajo cuando se le da la entrada correcta, y luego compruebe que su código proporciona la entrada correcta. Al mantener el código de procedimiento como SP y disparadores fuera de la base de datos y, en su lugar, hacer ese tipo de cosas en el código de la aplicación, dicho código de la aplicación es mucho más fácil de ejercer.
fuente
Una de las cosas que la gente parece no darse cuenta es que hacer todo el procesamiento en el servidor SQL no es necesariamente bueno, independientemente de los efectos en la calidad del código.
Por ejemplo, si necesita obtener algunos datos y luego calcular algo de los datos y luego almacenarlos en la base de datos. Hay dos opciones:
Puede pensar que la segunda solución es siempre la más rápida, pero definitivamente esto no es cierto. Estoy ignorando incluso si SQL no se ajusta bien al problema (es decir, la expresión regular y la manipulación de cadenas). Supongamos que tiene SQL CLR o algo similar, incluso para tener un lenguaje poderoso en la base de datos. Si toma 1 segundo hacer un viaje de ida y vuelta y obtener los datos y 1 segundo para almacenarlo, y luego 10 segundos para hacer el cálculo a través de él. Lo estás haciendo mal si lo estás haciendo todo en la base de datos.
Claro, te afeitas 2 segundos. Sin embargo, ¿prefirió perder el 100% (al menos) de un núcleo de CPU en su servidor de base de datos durante 10 segundos, o prefirió perder ese tiempo en su servidor web?
Los servidores web son fáciles de escalar, las bases de datos son extremadamente caras, especialmente las bases de datos SQL. La mayoría de las veces, los servidores web también son "sin estado" y pueden agregarse y eliminarse a su antojo sin configuración adicional para nada más que el equilibrador de carga.
Por lo tanto, piense no solo en afeitarse 2 segundos después de una operación, sino también en la escalabilidad. ¿Por qué desperdiciar un recurso costoso como los recursos del servidor de bases de datos cuando puede usar los recursos del servidor web mucho más baratos con un impacto en el rendimiento relativamente pequeño?
fuente
Me gusta mirarlo, ya que SQL solo debe tratar con los datos en sí. Las reglas de negocio que deciden cómo se verá la consulta pueden ocurrir en el código. La expresión regular o validación de la información debe hacerse en código. Se debe dejar SQL solo para unir su tabla, consultar sus datos, insertar datos limpios, etc.
Lo que se pasa a SQL debería ser datos limpios y SQL realmente no debería necesitar saber más de lo que necesita para almacenarlo, actualizarlo, eliminarlo o recuperar algo. He visto que muchos desarrolladores quieren arrojar su lógica y codificación de negocios en SQL porque piensan que los datos son su negocio. Desacople su lógica de sus datos y verá que su código se vuelve más limpio y fácil de administrar.
Sin embargo, solo mis $ 0.02.
fuente
En general, estoy de acuerdo en que el código debe controlar la lógica de negocios y la base de datos debe ser un hash libre de lógica. Pero aquí hay algunos contrapuntos:
La clave primaria, la clave externa y las restricciones requeridas (no nulas) podrían aplicarse mediante código. Las restricciones son la lógica empresarial. ¿Deberían quedar fuera de la base de datos ya que duplican lo que puede hacer el código?
¿Otras partes fuera de su control tocan la base de datos? Si es así, tener restricciones impuestas cerca de los datos es bueno. El acceso podría estar restringido a un servicio web que implementa la lógica, pero esto supone que usted estuvo allí "primero" y que tiene el poder de imponer el uso del servicio a las otras partes.
¿Su ORM realiza una inserción / actualización por separado para cada objeto? En caso afirmativo, tendrá graves problemas de rendimiento cuando procese por lotes grandes conjuntos de datos. Establecer operaciones es el camino a seguir. Un ORM tendrá problemas para modelar con precisión todos los conjuntos unidos posibles en los que podría realizar operaciones.
¿Considera que una "capa" es una división física por servidores o una división lógica? La ejecución de la lógica en cualquier servidor teóricamente podría caer bajo su capa lógica. Puede organizar la división compilando en diferentes DLL en lugar de dividir los servidores exclusivamente. Esto puede aumentar dramáticamente el tiempo de respuesta (pero sacrificando el rendimiento) mientras se mantiene la separación de las preocupaciones. Una DLL dividida se podría mover más tarde a otros servidores sin una nueva compilación para aumentar el rendimiento (a costa del tiempo de respuesta).
fuente
El modismo tiene más que ver con mantener las reglas comerciales, con los datos, junto con las relaciones (los datos, la estructura y las relaciones). No es una ventanilla única para cada problema, pero ayuda a evitar cosas como manualmente contadores de registros mantenidos, integridad de relación mantenida manualmente, etc., si estas cosas están disponibles a nivel de base de datos. Entonces, si alguien más aparece y extiende los programas o escribe otro programa que interactúa con la base de datos, no tendrá que descubrir cómo mantener la integridad de la base de datos del código anterior. El caso de un contador de registros mantenido manualmente es particularmente pertinente cuando alguien más quiere crear un nuevo programa para interactuar con la misma base de datos. Incluso si el programa recién creado tiene exactamente el código correcto para el contador, Es probable que el programa original y el nuevo que se ejecuta aproximadamente al mismo tiempo lo corrompan. Incluso hay un código que recupera registros y comprueba las condiciones antes de escribir un registro nuevo o actualizado (en código o como consultas separadas), cuando sea posible, esto a menudo se puede lograr directamente en la declaración de inserción o actualización. La corrupción de datos puede resultar nuevamente. El motor de base de datos garantiza la atomicidad; Se garantiza que una consulta de actualización o inserción con condiciones afectará solo a los registros que cumplan las condiciones y ninguna consulta externa puede cambiar los datos a la mitad de nuestra actualización. Hay muchas otras circunstancias en las que se usa el código cuando el motor de la base de datos funcionaría mejor. Se trata de integridad de datos y no de rendimiento. s incluso el código que recupera registros y comprueba las condiciones antes de escribir un registro nuevo o actualizado (en código o como consultas separadas), cuando sea posible, esto a menudo se puede lograr directamente en la declaración de inserción o actualización. La corrupción de datos puede resultar nuevamente. El motor de base de datos garantiza la atomicidad; Se garantiza que una consulta de actualización o inserción con condiciones afectará solo a los registros que cumplan las condiciones y ninguna consulta externa puede cambiar los datos a la mitad de nuestra actualización. Hay muchas otras circunstancias en las que se usa el código cuando el motor de la base de datos funcionaría mejor. Se trata de integridad de datos y no de rendimiento. s incluso el código que recupera registros y comprueba las condiciones antes de escribir un registro nuevo o actualizado (en código o como consultas separadas), cuando sea posible, esto a menudo se puede lograr directamente en la declaración de inserción o actualización. La corrupción de datos puede resultar nuevamente. El motor de base de datos garantiza la atomicidad; Se garantiza que una consulta de actualización o inserción con condiciones afectará solo a los registros que cumplan las condiciones y ninguna consulta externa puede cambiar los datos a la mitad de nuestra actualización. Hay muchas otras circunstancias en las que se usa el código cuando el motor de la base de datos funcionaría mejor. Se trata de integridad de datos y no de rendimiento. El motor de base de datos garantiza la atomicidad; Se garantiza que una consulta de actualización o inserción con condiciones afectará solo a los registros que cumplan las condiciones y ninguna consulta externa puede cambiar los datos a la mitad de nuestra actualización. Hay muchas otras circunstancias en las que se usa el código cuando el motor de la base de datos funcionaría mejor. Se trata de integridad de datos y no de rendimiento. El motor de base de datos garantiza la atomicidad; Se garantiza que una consulta de actualización o inserción con condiciones afectará solo a los registros que cumplan las condiciones y ninguna consulta externa puede cambiar los datos a la mitad de nuestra actualización. Hay muchas otras circunstancias en las que se usa el código cuando el motor de la base de datos funcionaría mejor. Se trata de integridad de datos y no de rendimiento.
Por lo tanto, en realidad es un buen lenguaje de diseño o regla general. Ninguna cantidad de rendimiento va a ayudar en un sistema con datos corruptos.
fuente
Como se mencionó anteriormente, el objetivo es enviar y recibir lo menos posible de la base de datos porque los viajes de ida y vuelta son muy costosos. Enviar declaraciones SQL una y otra vez es una pérdida de tiempo, especialmente en consultas más complejas.
El uso de procedimientos almacenados en la base de datos permite a los desarrolladores interactuar con la base de datos como una API, sin preocuparse por el complejo esquema en la parte posterior. También reduce los datos enviados al servidor ya que solo se envían el nombre y algunos parámetros. En este escenario, la mayoría de la lógica de negocios todavía puede estar en el código pero no en forma de SQL. El código esencialmente prepararía lo que se debe enviar o solicitar de la base de datos.
fuente
Hay algunas cosas para recordar:
fuente
Use la herramienta más adecuada para el trabajo. Para la integridad de los datos, esta suele ser la base de datos. Para reglas comerciales avanzadas, este es un sistema basado en reglas como JBoss Drools. Para la visualización de datos, este sería un marco de informes. etc.
Si tiene algún problema de rendimiento, luego debe ver si los datos se pueden almacenar en caché o si una implementación en la base de datos sería más rápida. En general, el costo de comprar servidores adicionales o energía adicional en la nube será mucho menor que el costo de mantenimiento adicional y el impacto de errores adicionales.
fuente