"Nunca haga en el código lo que puede hacer que el servidor SQL funcione bien para usted": ¿es esta una receta para un mal diseño?

193

Es una idea que he escuchado repetida en un puñado de lugares. Algunos reconocen más o menos que una vez que tratar de resolver un problema puramente en SQL supera un cierto nivel de complejidad, debería estar manejándolo en código.

La lógica detrás de la idea es que, en 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 + cacheando 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 mala práctica de diseño (y por qué). Las líneas se vuelven más borrosas cuando existe toda la lógica dentro de la base de datos y solo la está golpeando a través de un ORM.

    
pregunta PhonicUK 22.03.2014 - 15:16

14 respuestas

312

En palabras sencillas:

Estas son cosas que SQL está hecho para hacer y, créanlo o no, lo he visto en código:

  • se une - por lo tanto, se requeriría una manipulación compleja de la matriz
  • filtrando datos (donde): por código, sería necesario insertar y eliminar elementos de las listas
  • selección de columnas : por lo tanto, se requeriría una manipulación pesada de la lista o la matriz
  • funciones agregadas : por código, se requeriría que las matrices mantengan valores y casos complejos de cambio
  • integridad de la clave foránea : por lo tanto, se requerirían consultas antes de insertar y se supone que nadie utilizará los datos fuera de la aplicación
  • integridad de la clave principal : por código, se requerirían consultas antes de insertar y se supone que nadie utilizará los datos fuera de la aplicación

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 asume peligrosamente que solo se podrá acceder a la base de datos a través de la aplicación.

    
respondido por el user61852 22.07.2013 - 18:40
120

Lo expresaría de nuevo como "Nunca haga en el código lo que SQL Server puede hacer por usted bueno ".

Cosas como la manipulación de cadenas, el trabajo de expresiones regulares y otros que no haría en SQL Server (excepto SQL CLR).

Lo anterior tiende a hablar de cosas como: uniones, establecer operaciones y consultas. La intención detrás de esto es delegar gran parte del trabajo pesado a SQL Server (por lo que es bueno) y reducir la cantidad de IO tanto como sea posible (así que deje que SQL haga las uniones y filtre hacia abajo con una cláusula WHERE , devolviendo un conjunto de datos mucho más pequeño que de otra manera).

    
respondido por el Oded 23.10.2012 - 17:35
46
  

Nunca haga en el código lo que puede hacer que el servidor SQL haga bien por usted (el énfasis es mío)

La clave de la respuesta es que necesita 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 analizar la cantidad de datos que recupera y el número de viajes de ida y vuelta: si puede reducir la cantidad de datos enviando una tarea al servidor, sin aumentar el número de viajes de ida y vuelta, entonces la tarea pertenece en el servidor; Si la cantidad de datos permanece igual o aumenta sin disminuir simultáneamente el número de viajes de ida y vuelta, la tarea pertenece a su código.

Considere estos ejemplos:

  • Almacena una fecha de nacimiento y necesita calcular la edad de un grupo de usuarios. Puede hacer que el servidor SQL haga la resta, o puede hacerlo en su código. La cantidad de viajes de ida y vuelta permanece igual, y la cantidad de datos que se le devuelven aumenta. Por lo tanto, una solución basada en código gana
  • Almacena una fecha de nacimiento y necesita encontrar usuarios de entre 20 y 30 años. Puede volver a cargar a todos los usuarios en el cliente, hacer la resta para encontrar la edad y luego hacer el filtrado, pero enviando la lógica a SQL Server reduciría la cantidad de datos sin requerir un viaje de ida y vuelta adicional; por lo tanto, la solución basada en SQL gana.
respondido por el dasblinkenlight 23.10.2012 - 18:03
20

En resumen , sería correcto decir: "Nunca realice operaciones específicas de base de datos en su base de código" ya que son mejores abordado en su base de datos.

Vea el ejemplo de configurar las operaciones básicas . Como sabrá, RDBMS se crean para manejar un almacenamiento de datos y operaciones de manipulación comunes.

Además, la elección de proyecto de la base de datos juega un papel importante . Tener un RDBMS (MS SQL, Oracle, etc.) es diferente a las bases de datos NoSQL como RavenDB.

    
respondido por el ElYusubov 24.10.2012 - 18:15
13

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. Para que todo lo demás sea igual, su carga de trabajo general puede disminuir presionando el trabajo a la base de datos en lugar de a la aplicación.

Pero a medida que su producto escala, por lo general, es 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 superan en número a los servidores de base de datos por un factor de 10 a 1 o más. Agregar más servidores de aplicaciones es a menudo una simple cuestión de clonar un servidor existente en un nuevo hardware. Agregar nuevos servidores de bases de datos, por otro lado, es mucho más difícil en la mayoría de los casos.

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 en memcached o al poner en cola las actualizaciones en un registro del lado de la aplicación, o al buscar los datos una vez y al calcular las estadísticas en su aplicación, puede reducir drásticamente la carga de trabajo de su base de datos, evitando que tenga para recurrir a una configuración de cluster de DB aún más complicada y frágil.

    
respondido por el tylerl 23.10.2012 - 20:15
11

Creo que sería un mal diseño no usar la base de datos para lo que está destinado. Nunca he visto ninguna base de datos donde las reglas se aplicaran fuera de la base de datos que contuvieran buenos datos. Y he mirado cientos de bases de datos.

Entonces, las cosas que deben hacerse en una base de datos:

  • Auditoría (la auditoría solo de la aplicación no rastreará todos los cambios en el base de datos y por lo tanto es inútil).

  • Restricciones de ingerencia de datos que incluyen valores predeterminados, clave externa restricciones y reglas que siempre deben aplicarse a todos los datos. Todos Los datos no siempre se cambian o se insertan a través de una aplicación, hay son arreglos de datos únicos, especialmente de grandes conjuntos de datos que no están práctico hacer un registro a la vez (por favor actualice estos 100,000 registros que quedaron mal marcados como estado 1 cuando deberían ser 2 debido a un error de código de aplicación o actualice todos los registros del cliente A para cliente B porque la empresa B compró la empresa A) y las importaciones de datos y otras aplicaciones que puedan tocar la misma base de datos.

  • El filtrado de cláusulas DONDE y dónde (para reducir el número de registros enviado a través de la red)

respondido por el HLGEM 11.11.2012 - 13:54
5
  

"La optimización prematura es la raíz de todo mal (de todos modos, la mayoría) en la programación de computadoras" - Donald Knuth

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 han proporcionado. Su aplicación es el lugar para colocar el código que realmente funciona con los datos; desplegándolo, validándolo, etc.

Si bien el sentimiento en la línea del título es admirable y preciso hasta cierto punto (el meollo de la acción de filtrar, proyectar, agrupar, etc. debería en el abrumador número de casos debe dejarse en el 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 demostrar que SQL Server hace correctamente de manera aislada y repetitiva son muy pocas. SQL Management Studio es una gran base de datos IDE (especialmente teniendo en cuenta las otras opciones con las que he trabajado, como TOAD), pero tiene sus limitaciones, entre las que se encuentra que casi todo lo que se usa para hacer (o cualquier código de procedimiento que ejecute en la base de datos que se encuentra debajo) es, por definición, un "efecto secundario" (el estado de alteración se encuentra fuera del dominio del espacio de memoria de su proceso). Además, el código de procedimiento dentro de SQL Server es solo ahora, con los IDE y las herramientas más recientes, que se pueden 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 esta declaración particular si es encontrada por las pruebas) , Y, y Z, y la prueba X está diseñada para que la condición sea verdadera y se ejecute esa mitad, mientras que Y y Z ejecutan el "más". Eso, a su vez, supone que tiene una prueba que puede configurar la base de datos con un inicio en particular Estado, ejecute el código de procedimiento de la base de datos a través de alguna acción y confirme 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; asuma la capa de datos (y, para el caso, el DAL) sepa cómo hacer su trabajo cuando se le da la entrada correcta, y luego pruebe que su código proporciona la entrada correcta. Al mantener el código de procedimiento como los SP y los activadores 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.

    
respondido por el KeithS 23.10.2012 - 19:28
5

Una de las cosas que la gente parece no darse cuenta es que hacer todo su procesamiento en el servidor SQL no es necesariamente bueno, independientemente de los efectos en la calidad del código.

Por ejemplo, si necesita capturar algunos datos y luego calcular algo de los datos y luego almacenar esos datos en la base de datos. Hay dos opciones:

  • Agarre los datos en su aplicación, calcule dentro de su aplicación y luego envíe los datos a la base de datos
  • Cree un procedimiento almacenado o similar para capturar los datos, calcularlos y luego almacenarlos desde una sola llamada al servidor SQL.

Puedes pensar que la segunda solución es siempre la más rápida, pero esto definitivamente no es cierto. Ignoro, incluso si SQL es un mal ajuste para el problema (es decir, la expresión regular y la manipulación de cadenas). Supongamos que tiene SQL CLR o algo similar para tener incluso un lenguaje poderoso en la base de datos. Si demora 1 segundo hacer un viaje de ida y vuelta y obtener los datos y 1 segundo para almacenarlo, y luego 10 segundos para realizar el cálculo. Lo estás haciendo mal si lo estás haciendo todo en la base de datos.

Claro, te afeitas 2 segundos. Sin embargo, ¿preferiría perder el 100% de (al menos) un núcleo de CPU en su servidor de base de datos durante 10 segundos, o preferiría perder ese tiempo en su servidor web?

Los servidores web son fáciles de ampliar, por otro lado, 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 se pueden agregar y eliminar a su antojo sin ninguna configuración adicional a nada, excepto al equilibrador de carga.

Entonces, piense no solo en reducir 2 segundos de una operación, sino también en escalabilidad. ¿Por qué desperdiciar un recurso costoso como los recursos del servidor de bases de datos cuando puede utilizar recursos del servidor web mucho más baratos con un impacto en el rendimiento relativamente pequeño?

    
respondido por el Earlz 26.10.2012 - 19:53
4

Me gusta verlo como SQL solo debería 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 la validación de la información se debe hacer en código. Debe dejarse SQL para unirse a su tabla, consultar sus datos, insertar datos limpios, etc.

Lo que se pasa a SQL debería ser datos limpios y SQL no debería necesitar saber nada más de lo que necesita para almacenarlo, actualizarlo, eliminarlo o recuperar algo. He visto demasiados desarrolladores que quieren lanzar su lógica de negocio y codificación en SQL porque piensan que los datos son su negocio. Desconecte su lógica de sus datos y encontrará que su código se vuelve más limpio y más fácil de administrar.

Sin embargo, solo mi $ 0.02.

    
respondido por el Stanley Glass Jr 23.10.2012 - 18:14
3

Generalmente estoy de acuerdo en que el código debe controlar la lógica de negocios y la base de datos debe ser un hash sin lógica. Pero aquí hay algunos puntos en contra:

El código podría imponer restricciones primarias, de clave externa y requeridas (no nulas). Las restricciones son la lógica de negocios. ¿Deberían dejarse fuera de la base de datos ya que duplican lo que puede hacer el código?

¿Las 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 implemente 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? Si es así, entonces tendrá graves problemas de rendimiento al procesar 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 con los que podría realizar operaciones.

¿Considera que una "capa" es una división física por servidores o una división lógica? Ejecutar la lógica en cualquier servidor podría teóricamente aún caer bajo su capa lógica. Puede organizar la división compilando en diferentes DLL en lugar de dividir servidores exclusivamente. Esto puede aumentar dramáticamente el tiempo de respuesta (pero sacrificando todo el tiempo) mientras se mantiene la separación de las preocupaciones. Una DLL dividida podría luego trasladarse a otros servidores sin una nueva compilación para aumentar el rendimiento (a costa del tiempo de respuesta).

    
respondido por el mike30 23.10.2012 - 18:26
3

La expresión idiomática tiene más que ver con mantener las reglas de negocios, hacer con los datos, junto con las relaciones (los datos y la estructura y las relaciones). No es una ventanilla única para cada problema, pero ayuda a evitar cosas como contadores de registros mantenidos manualmente, integridad de la relación mantenida manualmente, etc., si estas cosas están disponibles en el nivel de la 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 averiguar 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 desea 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 se ejecuten aproximadamente al mismo tiempo para corromperlo. Incluso existe un código que recupera los registros y verifica las condiciones antes de escribir un registro nuevo o actualizado (en código o como consultas separadas), cuando, de ser posible, esto puede lograrse directamente en la declaración de inserción o actualización. La corrupción de datos puede volver a resultar. 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 con las condiciones y ninguna consulta externa puede cambiar los datos a la mitad de nuestra actualización. Hay muchas otras circunstancias en las que el código se usa cuando el motor de la base de datos funcionaría mejor. Se trata de la integridad de los datos y no del rendimiento.

Así que en realidad es un buen lenguaje de diseño o regla de oro. Ninguna cantidad de rendimiento ayudará en un sistema con datos corruptos.

    
respondido por el Chris 24.10.2012 - 01:08
0

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 en cuanto al tiempo. Enviar las declaraciones de 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 aún puede estar en el código pero no en la forma de SQL. El código básicamente preparará lo que se enviará o solicitará desde la base de datos.

    
respondido por el Laurent Goderre 24.10.2012 - 02:02
0

Hay algunas cosas para recordar:

  • Una base de datos relacional debe garantizar la integridad referencial a través de claves externas
  • La escala de una base de datos puede ser difícil y costosa. La escala de un servidor web es mucho más fácil simplemente agregando más servidores web. Diviértete intentando agregar más poder del servidor SQL.
  • Con C # y LINQ, puedes hacer tus "uniones" y otras cosas a través del código para que puedas obtener lo mejor de ambos mundos en muchos casos
respondido por el Joe Phillips 25.10.2012 - 03:56
0
  

"La optimización prematura es la raíz de todo mal" - Donald Knuth

Utilice la herramienta más adecuada para el trabajo. Para la integridad de los datos, esta es a menudo la base de datos. Para reglas de negocios avanzadas, este es un sistema basado en reglas como JBoss Drools. Para la visualización de datos, esto sería un marco de informes. etc.

Si tiene algún problema de rendimiento, debería 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 potencia de nube adicional será mucho más bajo que el costo de mantenimiento adicional y el impacto de errores adicionales.

    
respondido por el parasietje 02.02.2014 - 02:04

Lea otras preguntas en las etiquetas