download java db driver library netbeans
¿Cuáles son los pros y los contras de realizar cálculos en sql vs. en su aplicación? (12)
shopkeeper
tabla del shopkeeper
tiene los siguientes campos:
id (bigint),amount (numeric(19,2)),createddate (timestamp)
Digamos que tengo la tabla anterior. Quiero obtener los registros de ayer y generar un informe haciendo que la cantidad se imprima en centavos.
Una forma de hacerlo es realizar cálculos en mi aplicación Java y ejecutar una consulta simple
Date previousDate ;// $1 calculate in application
Date todayDate;// $2 calculate in application
select amount where createddate between $1 and $2
y luego recorrer los registros y convertir la cantidad a centavos en mi aplicación java y generar el informe
Otra forma es como realizar cálculos en la consulta sql en sí:
select cast(amount * 100 as int) as "Cents"
from shopkeeper where createddate between date_trunc(''day'', now()) - interval ''1 day'' and date_trunc(''day'', now())
y luego recorrer los registros y generar el informe
De una manera, todo mi procesamiento se realiza en una aplicación java y se activa una simple consulta. En otro caso, todas las conversiones y cálculos se realizan en consulta Sql.
El caso de uso anterior es solo un ejemplo; en un escenario real, una tabla puede tener muchas columnas que requieren un procesamiento del mismo tipo.
¿Puede decirme qué enfoque es mejor en términos de rendimiento y otros aspectos y por qué?
Depende de muchos factores, pero lo más importante:
- complejidad de los cálculos (se prefiere hacer crujidos complejos en un servidor de aplicaciones, ya que eso se escala, en lugar de un servidor db, que se amplía)
- volumen de datos (si necesita acceder / agregar una gran cantidad de datos, hacerlo en el servidor db ahorrará ancho de banda, y el disco io si los agregados se pueden hacer dentro de los índices)
- conveniencia (sql no es el mejor lenguaje para el trabajo complejo, especialmente no es excelente para el trabajo de procedimientos, pero es muy bueno para el trabajo basado en conjuntos; sin embargo, el mal manejo de errores)
Como siempre, si devuelve los datos al servidor de la aplicación, minimizar las columnas y las filas le resultará ventajoso. Asegurarse de que la consulta esté ajustada y adecuadamente indexada ayudará a cualquiera de los escenarios.
Re su nota:
y luego recorrer los registros
Hacer bucles a través de registros casi siempre es lo incorrecto en sql; es preferible escribir una operación basada en conjuntos.
Como regla general , prefiero mantener al mínimo el trabajo de la base de datos "almacenar estos datos, buscar estos datos"; sin embargo, siempre hay ejemplos de situaciones en las que una consulta elegante en el servidor puede ahorrar mucho ancho de banda.
También considere: si esto es computacionalmente costoso, ¿puede almacenarse en caché en alguna parte?
Si quieres un "que sea mejor"; codifíquelo en ambos sentidos y compárelo (teniendo en cuenta que un primer borrador de cualquiera de ellos probablemente no esté 100% sintonizado). Pero factor en el uso típico de eso: si, en realidad, se está llamando 5 veces (por separado) a la vez, entonces simule eso: no compare solo un "1 de estos frente a uno de esos".
En este caso, probablemente esté un poco mejor haciendo el cálculo en SQL, ya que es probable que el motor de la base de datos tenga rutinas aritméticas decimales más eficientes que Java.
En general, sin embargo, para los cálculos de nivel de fila no hay mucha diferencia.
Donde hace la diferencia es:
- Los cálculos agregados como SUM (), AVG (), MIN (), MAX () aquí el motor de la base de datos será un orden de magnitud más rápido que una implementación de Java.
- En cualquier lugar, el cálculo se usa para filtrar filas. Filtrar en el DB es mucho más eficiente que leer una fila y luego descartarla.
En general, haga cosas en SQL si hay posibilidades de que también otros módulos o componentes en el mismo u otros proyectos necesiten obtener esos resultados. una operación atómica del lado del servidor también es mejor porque solo necesita invocar el proceso almacenado desde cualquier herramienta de administración de db para obtener los valores finales sin más procesamiento.
En algunos casos, esto no se aplica, pero cuando lo hace tiene sentido. también, en general, la caja db tiene el mejor hardware y rendimiento.
Formar un punto de vista del rendimiento: se trata de una operación aritmética muy simple que casi con certeza se puede realizar mucho más rápido que extraer realmente los datos de los discos subyacentes a la base de datos. Además, calcular los valores en la cláusula where es probable que sea muy rápido en cualquier tiempo de ejecución. En resumen, el cuello de botella debe ser disco IO, no el cálculo de los valores.
De acuerdo con la legibilidad, creo que si usa un ORM debe hacerlo en el entorno de su servidor de aplicaciones, porque el ORM le permitirá trabajar con los datos subyacentes muy fácilmente, usando operaciones basadas en conjuntos. Si va a escribir SQL en bruto de todos modos, no hay nada de malo en hacer el cálculo allí, Su SQL también se verá un poco más agradable y más fácil de leer si está formateado correctamente.
Fundamentalmente, el "desempeño" no está definido.
El que más me importa es el tiempo del desarrollador.
Escribe la consulta SQL. Si es demasiado lento o el DB se convierte en un cuello de botella, entonces reconsidere. En ese momento, podrá comparar los dos enfoques y tomar una decisión basada en datos reales relevantes para su configuración (hardware y cualquier pila en la que se encuentre).
Las otras respuestas a esta pregunta son interesantes. Sorprendentemente, nadie ha respondido tu pregunta. Te estás preguntando:
- ¿Es mejor enviar a Cents en la consulta? No creo que el elenco de centavos agregue nada en su consulta.
- ¿Es mejor usar now () en la consulta? Preferiría pasar fechas en la consulta en lugar de calcularlas en la consulta.
Más información: para la pregunta uno, quiere estar seguro de que agregar las fracciones funciona sin errores de redondeo. Creo que el 19,2 numérico es razonable para el dinero y en el segundo caso los enteros están bien. Usar un flotador por dinero es incorrecto por esta razón.
Para la segunda pregunta, me gusta tener el control total como programador de qué fecha se considera "ahora". Puede ser difícil escribir pruebas unitarias automáticas cuando se usan funciones como ahora (). Además, cuando tiene un script de transacción más largo, puede ser útil establecer una variable igual a now () y usar la variable para que toda la lógica use exactamente el mismo valor.
No creo que se puedan razonar las diferencias de rendimiento sin ejemplos específicos y puntos de referencia, pero tengo otra opinión:
¿Qué puedes mantener mejor? Por ejemplo, es posible que desee cambiar su interfaz de Java a Flash, HTML5, C ++ u otra cosa. Una gran cantidad de programas han sufrido dicho cambio, o incluso existen en más de un idioma, porque necesitan trabajar en múltiples dispositivos.
Incluso si tiene una capa intermedia adecuada (del ejemplo dado, parece que ese no es el caso), esa capa podría cambiar y JBoss podría convertirse en Ruby / Rails.
Por otro lado, es poco probable que reemplace el SQL-backend con algo que no sea un DB relacional con SQL e incluso si lo hace, tendrá que volver a escribir el front-end desde cero de todos modos, por lo que el punto es discutible.
Mi idea es que si haces cálculos en la BD, será mucho más fácil escribir una segunda interfaz o capa intermedia más adelante, porque no tienes que volver a implementar todo. Sin embargo, en la práctica, pienso "¿dónde puedo hacer esto con un código que las personas entiendan?" Es el factor más importante.
No hay negro / blanco con respecto a qué partes de la lógica de acceso a datos se deben realizar en SQL y qué partes se deben realizar en su aplicación. Me gusta la redacción de Mark Gravell , distinguiendo entre
- cálculos complejos
- cálculos intensivos de datos
El poder y la expresividad de SQL están muy subestimados. Desde la introducción de las funciones de ventana , se pueden realizar muchos cálculos no estrictamente orientados de forma muy fácil y elegante en la base de datos.
Se deben seguir tres reglas generales, independientemente de la arquitectura general de la aplicación:
- mantener la cantidad de datos transferidos entre la base de datos y la aplicación delgada (a favor de calcular cosas en el DB)
- mantenga la cantidad de datos cargados desde el disco por la base de datos delgada (a favor de dejar que la base de datos optimice las declaraciones para evitar el acceso innecesario a los datos)
- no empuje la base de datos a sus límites de CPU con cálculos concurrentes y complejos (a favor de extraer datos en la memoria de la aplicación y realizar cálculos allí)
En mi experiencia, con un DBA decente y un poco de conocimiento decente sobre su base de datos decente, no se encontrará con los límites de CPU de su DB muy pronto.
Algunas lecturas adicionales donde se explican estas cosas:
Para simplificar la forma de responder esto, sería mirar el equilibrio de carga. Desea colocar la carga donde tiene la mayor capacidad (si tiene sentido). En la mayoría de los sistemas, el servidor SQL se convierte rápidamente en un cuello de botella, por lo que la respuesta probable es que no desea que SQL haga una onza de trabajo más de lo necesario.
También en la mayoría de las arquitecturas son los servidores SQL los que componen el núcleo del sistema y los sistemas externos que se agregan.
Pero la matemática anterior es tan trivial que a menos que estés presionando tu sistema hasta el límite, el mejor lugar para ponerlo es donde quieras ponerlo. Si las matemáticas no fueran triviales, como calcular sin / cos / tan para decir un cálculo de distancia, entonces el esfuerzo podría ser no trivial y requerir una planificación y prueba cuidadosas.
Permítanme usar una metáfora: si quiere comprar un collar de oro en París, el orfebre podría sentarse en Ciudad del Cabo o en París, eso es una cuestión de habilidad y gusto. Pero nunca enviarías toneladas de mineral de oro de Sudáfrica a Francia por eso. El mineral se procesa en el sitio de la mina (o al menos en el área general), solo se envía el oro. Lo mismo debería ser cierto para aplicaciones y bases de datos.
En lo que respecta a PostgreSQL , puede hacer casi cualquier cosa en el servidor, de manera bastante eficiente. El RDBMS sobresale en consultas complejas. Para las necesidades de procedimiento, puede elegir entre una variedad de lenguajes de script del lado del servidor : tcl, python, perl y muchos más. Sobre todo uso PL/pgSQL , sin embargo.
El peor escenario sería ir repetidamente al servidor por cada fila de un conjunto más grande. (Eso sería como enviar una tonelada de mineral por vez).
Segundo en línea , si envía una cascada de consultas, cada una dependiendo de la anterior, mientras que todas podrían hacerse en una consulta o procedimiento en el servidor. (Eso es como enviar el oro, y cada una de las joyas con un barco separado, secuencialmente).
Ir y venir entre la aplicación y el servidor es costoso. Para servidor y cliente Trate de reducir eso y ganará, por ejemplo: use procedimientos del lado del servidor y / o SQL sofisticado cuando sea necesario.
Acabamos de terminar un proyecto en el que empaquetamos casi todas las consultas complejas en funciones de Postgres. La aplicación entrega los parámetros y obtiene los conjuntos de datos que necesita. Rápido, limpio, simple (para el desarrollador de la aplicación), I / O reducido a un mínimo ... un collar brillante con una huella baja en carbono.
Si escribe sobre ORM o escribe aplicaciones informales de bajo rendimiento, use cualquier patrón que simplifique la aplicación. Si está escribiendo una aplicación de alto rendimiento y pensando cuidadosamente acerca de la escala, ganará moviendo el procesamiento a los datos. Recomiendo encarecidamente mover el procesamiento a los datos.
Pensemos en esto en dos pasos: (1) transacciones OLTP (número pequeño de registros). (2) OLAP (escaneos largos de muchos registros).
En el caso de OLTP, si quiere ser rápido (10k - 100k transacciones por segundo), debe eliminar la contención de bloqueo, bloqueo y bloqueo muerto de la base de datos. Esto significa que debe eliminar puestos largos en las transacciones: los viajes de ida y vuelta del cliente a la base de datos para mover el procesamiento al cliente son uno de esos puestos largos. No puede tener transacciones de larga duración (para hacer lectura / actualización atómica) y tiene un rendimiento muy alto.
Re: escalado horizontal. Las bases de datos modernas se escalan horizontalmente. Esos sistemas ya implementan HA y tolerancia a fallas. Aproveche eso y trate de simplificar su espacio de aplicación.
Echemos un vistazo a OLAP, en este caso debería ser obvio que arrastrar posibles datos de terrabytes a la aplicación es una idea horrible. Estos sistemas están diseñados específicamente para operar de manera extremadamente eficiente contra datos de columna comprimidos y preorganizados. Los sistemas OLAP modernos también se escalan horizontalmente y cuentan con sofisticados planificadores de consultas que dispersan el trabajo horizontalmente (moviendo internamente el procesamiento a los datos).
Ya sea para realizar cálculos en la parte delantera o en el backend está muy decidido si podemos determinar nuestro objetivo en la implementación del negocio. En el momento, el código de java puede tener un mejor rendimiento que un código sql, bien escrito o podría ser viceversa. Pero aun así, si estás confundido, puedes intentar determinar primero:
- Si puede lograr algo sencillo a través de la base de datos sql, entonces mejor que lo haga, ya que db funcionará mucho mejor y realizará cálculos allí y luego con la búsqueda de resultados. Sin embargo, si el cálculo real requiere demasiado cálculo de aquí y de allí, entonces puede ir con el código de la aplicación. ¿Por qué? Debido a que los escenarios son similares a los bucles en la mayoría de los casos, sql no los maneja mejor, por lo que los lenguajes frontales están mejor diseñados para estas cosas.
- En caso de que se requiera un cálculo similar desde muchos lugares, obviamente, colocar el código de cálculo en el extremo db será mejor para mantener las cosas en el mismo lugar.
- Si hay muchos cálculos por hacer para alcanzar el resultado final a través de muchas consultas diferentes, entonces también puede usar db end ya que puede colocar el mismo código en un procedimiento almacenado para obtener un mejor rendimiento que recuperar los resultados del backend y luego calcularlos en la parte frontal fin.
Hay muchos otros aspectos que puede pensar antes de decidir dónde colocar el código. Una percepción es totalmente incorrecta: todo se puede hacer mejor en Java (código de la aplicación) y / o todo es mejor que lo haga el db (código sql).