sql >> Base de Datos >  >> RDS >> Database

Comparación de SQL, generadores de consultas y ORM


Introducción

El uso de una base de datos para administrar los datos de su aplicación es una de las opciones más comunes para la persistencia de datos. Las bases de datos permiten el almacenamiento y la recuperación rápidos de información, brindan garantías de integridad de datos y ofrecen persistencia más allá de la vida útil de una instancia de aplicación individual. Hay innumerables tipos de bases de datos disponibles para cumplir con los requisitos de su proyecto y sus preferencias.

Sin embargo, trabajar directamente con bases de datos desde su aplicación no siempre es fácil. Las diferencias en la forma en que se representan las estructuras de datos a menudo generan desafíos. La dificultad para expresar sutilezas sobre las relaciones entre diferentes entidades también puede causar problemas. Para abordar esto, se han creado muchas herramientas diferentes para ayudar a actuar como una interfaz entre la aplicación central y la capa de datos.

En esta guía, veremos algunas de las diferencias que surgen entre tres enfoques comunes:SQL sin procesar, generadores de consultas y ORM (asignadores relacionales de objetos). Compararemos algunos de los beneficios y desventajas de cada enfoque y luego terminaremos con un glosario de términos de uso común para ayudarlo a familiarizarse con algunos conceptos clave.

Como resumen simplificado, aquí hay una vista general de las fortalezas y debilidades de cada enfoque:

Enfoque Base de datos / Programación enfocada Gestión práctica Nivel de abstracción Nivel de complejidad
SQL sin formato orientado a base de datos alto ninguno bajo
Creadores de consultas mixto bajo bajo bajo
ORM orientado a la programación bajo alto alto


Gestionar datos con raw SQL u otro lenguaje de consulta nativo de la base de datos

Algunas aplicaciones interactúan directamente con la base de datos al escribir y ejecutar consultas utilizando el idioma nativo compatible con el motor de la base de datos. A menudo, un controlador de base de datos es todo lo que se necesita para conectarse, autenticarse y comunicarse con la instancia de la base de datos.

Los desarrolladores pueden enviar consultas escritas en el idioma nativo de la base de datos a través de la conexión. A cambio, la base de datos proporcionará los resultados de la consulta, también en uno de sus formatos nativos. Para muchas bases de datos relacionales, el lenguaje de consulta elegido es SQL.

La mayoría de las bases de datos relacionales, así como algunas bases de datos no relacionales, admiten un lenguaje de consulta estructurado, también conocido como SQL, para crear y ejecutar consultas eficaces. SQL se ha utilizado para administrar datos desde la década de 1970, por lo que cuenta con un buen soporte y estandarizado hasta cierto punto.


Beneficios de las consultas nativas

El uso de SQL u otro lenguaje nativo de la base de datos tiene algunos beneficios claros.

Una ventaja es que los desarrolladores escriben y administran las consultas de la base de datos y manejan los resultados de manera explícita. Si bien esto puede ser mucho trabajo adicional, significa que hay pocas sorpresas en términos de lo que almacena la base de datos, cómo representa sus datos y cómo proporcionará esos datos cuando se recuperen más tarde. La falta de abstracción significa que hay menos "partes móviles" que pueden generar incertidumbre.

Un ejemplo de esto es el rendimiento. Si bien las capas de abstracción sofisticadas generan consultas SQL mediante la traducción de declaraciones de programación, el SQL generado puede ser muy ineficiente. Las cláusulas innecesarias, las consultas demasiado amplias y otros percances pueden provocar operaciones de base de datos lentas que pueden ser frágiles y difíciles de depurar. Al escribir de forma nativa en SQL, puede emplear todo su conocimiento del dominio y sentido común para evitar muchas clases de problemas de consulta

Otra razón para usar consultas nativas de bases de datos es la flexibilidad. Es probable que ninguna abstracción pueda ser tan flexible como el lenguaje de consulta de la base de datos nativa. Los niveles más altos de abstracción intentan cerrar la brecha entre dos paradigmas diferentes, que pueden restringir los tipos de operaciones que pueden expresar. Sin embargo, al escribir en SQL sin procesar, puede aprovechar todas las características de su motor de base de datos y expresar consultas más complejas.



Inconvenientes de las consultas nativas

Si bien la consulta nativa tiene algunos puntos fuertes definidos, no está exenta de problemas.

Al interactuar con una base de datos desde una aplicación que utiliza SQL simple, debe comprender la estructura de datos subyacente para poder redactar consultas válidas. Usted es completamente responsable de traducir entre los tipos de datos y las estructuras que emplea su aplicación y las construcciones disponibles dentro del sistema de base de datos.

Otra cosa a tener en cuenta cuando se trabaja con SQL sin procesar es que depende completamente de usted administrar la seguridad de su entrada. Esto es especialmente cierto si está almacenando datos proporcionados por usuarios externos, donde la entrada especialmente diseñada podría inducir a su base de datos a exponer información que no tenía la intención de permitir.

Este tipo de explotación se llama inyección de SQL y es un problema potencial siempre que la entrada del usuario pueda afectar el estado de la base de datos. Las herramientas de mayor abstracción a menudo desinfectan la entrada del usuario automáticamente, ayudándole a evitar este tipo de problemas.

Trabajar con lenguajes de consulta nativos casi siempre significa redactar consultas con cadenas regulares. Este puede ser un proceso doloroso en los casos en los que debe escapar de la entrada y concatenar cadenas para crear una consulta válida. Las operaciones de su base de datos pueden verse envueltas en muchas capas de manipulación de cadenas que tienen un alto potencial para manipular datos accidentalmente.



Resumen de consultas nativas

Si bien hemos hablado principalmente de SQL en esta sección, la mayor parte de la información aquí se aplica igualmente bien a cualquier lenguaje de consulta de base de datos nativo. Para resumir, SQL sin formato o el uso directo de cualquier lenguaje de consulta equivalente lo acerca más a las abstracciones utilizadas por la base de datos para almacenar y administrar los datos, pero lo obliga a hacer todo el trabajo pesado de administrar sus datos manualmente.




Administración de datos con generadores de consultas

Un enfoque alternativo al uso de lenguajes de consulta nativos de bases de datos como SQL es usar una herramienta o biblioteca llamada generador de consultas para comunicarse con su base de datos.


¿Qué son los generadores de consultas SQL?

Un generador de consultas SQL agrega una capa de abstracción sobre los lenguajes de consulta nativos de la base de datos sin procesar. Lo hacen al formalizar patrones de consulta y proporcionar métodos o funciones que agregan saneamiento de entrada y escapan automáticamente de los elementos para facilitar la integración en las aplicaciones.

Las estructuras y acciones admitidas por la capa de la base de datos aún son bastante reconocibles cuando se utilizan generadores de consultas SQL. Esto le permite trabajar con datos mediante programación sin dejar de estar relativamente cerca de los datos.

Por lo general, los generadores de consultas proporcionan una interfaz que usa métodos o funciones para agregar una condición a una consulta. Al encadenar métodos, los desarrolladores pueden componer consultas de base de datos completas a partir de estas "cláusulas" individuales.



Beneficios de los generadores de consultas SQL

Debido a que los generadores de consultas usan las mismas construcciones (métodos o funciones) que el resto de su aplicación, los desarrolladores a menudo las encuentran más fáciles de administrar a largo plazo que las consultas de bases de datos sin procesar escritas como cadenas. Es sencillo notar la diferencia entre operadores y datos y es fácil descomponer consultas en fragmentos lógicos que manejan partes específicas de una consulta.

Para algunos desarrolladores, otra ventaja de usar un generador de consultas SQL es que no siempre oculta el lenguaje de consulta subyacente. Aunque las operaciones pueden usar métodos en lugar de cadenas, puede ser bastante transparente, lo que facilita que aquellos familiarizados con la base de datos entiendan lo que hará una operación. Este no siempre es el caso cuando se utilizan mayores niveles de abstracción.

Los generadores de consultas SQL a menudo también admiten múltiples backends de datos, abstrayendo algunas de las diferencias sutiles en varias bases de datos relacionales, por ejemplo. Esto le permite usar las mismas herramientas para proyectos que usan diferentes bases de datos. Incluso puede facilitar un poco la migración a una nueva base de datos.



Inconvenientes de los generadores de consultas SQL

Los generadores de consultas SQL sufren algunas de las mismas desventajas que los lenguajes de consulta nativos.

Una crítica popular es que los generadores de consultas SQL aún requieren que comprenda y tenga en cuenta las estructuras y capacidades de la base de datos. Esta no es una abstracción lo suficientemente útil para algunos desarrolladores. Esto significa que debe tener un conocimiento bastante bueno de SQL además de la sintaxis y las capacidades específicas del propio generador de consultas.

Además, los creadores de consultas SQL aún requieren que defina cómo los datos que recupera se relacionan con los datos de su aplicación. No hay sincronización automática entre sus objetos en memoria y los de la base de datos.

Si bien los generadores de consultas a menudo emulan el lenguaje de consulta con el que están diseñados para trabajar, la capa adicional de abstracción puede significar que, a veces, ciertas operaciones no son posibles con los métodos proporcionados. Por lo general, hay un modo "sin procesar" para enviar consultas directamente al backend, sin pasar por la interfaz típica del generador de consultas, pero esto evita el problema en lugar de resolverlo.



Resumen de los generadores de consultas SQL

En general, los generadores de consultas SQL ofrecen una fina capa de abstracción que se enfoca específicamente en algunos de los principales puntos débiles de trabajar directamente con lenguajes nativos de bases de datos. Los generadores de consultas SQL funcionan casi como un sistema de plantillas para consultas, lo que permite a los desarrolladores caminar por la línea entre trabajar directamente con la base de datos y agregar capas adicionales de abstracción.




Manejo de datos con ORMs

Un paso más arriba en la jerarquía de abstracción son los ORM. Los ORM generalmente apuntan a una abstracción más completa con la esperanza de integrarse con los datos de la aplicación de manera más fluida.


¿Qué son los ORM?

Los mapeadores relacionales de objetos, u ORM, son piezas de software dedicadas a traducir entre las representaciones de datos en bases de datos relacionales y la representación en la memoria utilizada con la programación orientada a objetos (OOP). El ORM proporciona una interfaz orientada a objetos para los datos dentro de la base de datos, intentando utilizar conceptos de programación familiares y reducir la cantidad de código repetitivo necesario para acelerar el desarrollo.

En general, los ORM sirven como una capa de abstracción destinada a ayudar a los desarrolladores a trabajar con bases de datos sin cambiar drásticamente el paradigma orientado a objetos. Esto puede ser útil al reducir la carga mental de adaptarse a las especificaciones del formato de almacenamiento de una base de datos.

En particular, los objetos en la programación orientada a objetos tienden a codificar mucho estado dentro de ellos y pueden tener relaciones complejas con otros objetos a través de la herencia y otros conceptos de programación orientada a objetos. Mapear esta información de manera confiable en un paradigma relacional orientado a tablas a menudo no es sencillo y puede requerir una buena comprensión de ambos sistemas. Los ORM intentan aligerar esta carga al automatizar parte de este mapeo y al proporcionar interfaces expresivas para los datos dentro del sistema.



¿Son los desafíos de los ORM específicos para la programación orientada a objetos? y bases de datos relacionales?

Por definición, los ORM están diseñados específicamente para interactuar entre lenguajes de aplicaciones orientados a objetos y bases de datos relacionales. Sin embargo, tratar de mapear y traducir entre las abstracciones de estructuras de datos utilizadas en los lenguajes de programación y las utilizadas por los almacenes de bases de datos es un problema más general que puede existir siempre que las abstracciones no se alineen correctamente.

Según el paradigma de programación (orientado a objetos, funcional, procedimental, etc.) y el tipo de base de datos (relacional, documento, clave-valor, etc.), diferentes cantidades de abstracción pueden ser útiles. Muchas veces, la complejidad de las estructuras de datos dentro de la aplicación determina qué tan fácil es interactuar con el almacén de datos.

La programación orientada a objetos tiende a producir muchas estructuras con estados y relaciones significativos que deben tenerse en cuenta. Algunos otros paradigmas de programación son más explícitos acerca de dónde se almacena el estado y cómo se gestiona. Por ejemplo, los lenguajes puramente funcionales no permiten el estado mutable, por lo que el estado suele ser una entrada para funciones u objetos que generan un nuevo estado. Esta clara separación de los datos de las acciones, así como la claridad de los ciclos de vida del estado, pueden ayudar a simplificar la interacción con la base de datos.

De cualquier manera, a menudo está disponible la opción de interactuar con una base de datos a través de un software que mapea entre dos representaciones diferentes. Entonces, mientras que los ORM describen un subconjunto específico de estos con desafíos únicos, el mapeo entre la memoria de la aplicación y el almacenamiento persistente a menudo requiere consideración, independientemente de los detalles.



ORM de registro activo frente a mapeador de datos

Diferentes ORM emplean diferentes estrategias para mapear entre la aplicación y las estructuras de la base de datos. Las dos categorías principales son el patrón de registro activo y el patrón del mapeador de datos .

El patrón de registro activo intenta encapsular los datos de la base de datos dentro de la estructura de objetos dentro de su código. Los objetos contienen métodos para guardar, actualizar o eliminar de la base de datos y los cambios en sus objetos están destinados a reflejarse fácilmente en la base de datos. En general, un objeto de registro activo en su aplicación representa un registro dentro de una base de datos.

Las implementaciones de registros activos le permiten administrar su base de datos creando y conectando clases e instancias dentro de su código. Dado que estos generalmente asignan instancias de clase directamente a los registros de la base de datos, es fácil conceptualizar lo que hay en su base de datos si comprende qué objetos se utilizan en su código.

Desafortunadamente, esto también puede tener algunas desventajas importantes. Las aplicaciones tienden a estar muy estrechamente acopladas con la base de datos, lo que puede causar problemas al intentar migrar a una nueva base de datos o incluso al probar su código. Su código tiende a depender de la base de datos para llenar los espacios que se descargaron de sus objetos. La traducción "mágica" entre estos dos dominios también puede provocar problemas de rendimiento, ya que el sistema intenta asignar sin problemas objetos complejos a la estructura de datos subyacente.

El patrón del mapeador de datos es el otro patrón ORM común. Al igual que el patrón de registro activo, el mapeador de datos intenta actuar como una capa independiente entre su código y su base de datos que media entre los dos. Sin embargo, en lugar de tratar de integrar a la perfección los objetos y los registros de la base de datos, se enfoca en tratar de desacoplarlos y traducirlos mientras permite que cada uno exista de forma independiente. Esto puede ayudar a separar la lógica empresarial de los detalles relacionados con la base de datos que se ocupan de las asignaciones, la representación, la serialización, etc.

Entonces, en lugar de dejar que el sistema ORM descubra cómo mapear entre los objetos y las tablas de la base de datos, el desarrollador es responsable de mapear explícitamente entre los dos. Esto puede ayudar a evitar un acoplamiento estrecho y operaciones entre bastidores a expensas de mucho más trabajo para determinar las asignaciones adecuadas.



Beneficios de los ORM

Los ORM son populares por muchas razones.

Ayudan a abstraer el dominio de datos subyacente a algo sobre lo que es fácil razonar dentro del contexto de su aplicación. En lugar de pensar en el almacenamiento de datos como un sistema independiente, los ORM lo ayudan a acceder y administrar los sistemas de datos como una extensión de su trabajo actual. Esto puede ayudar a los desarrolladores a trabajar más rápido en la lógica comercial central en lugar de atascarse en los matices de sus backends de almacenamiento.

Otro efecto secundario de esto es que los ORM eliminan gran parte del repetitivo necesario para interactuar con las bases de datos. Los ORM a menudo vienen con herramientas de migración que lo ayudan a administrar los cambios en el esquema de la base de datos en función de los cambios realizados en su código. No necesariamente necesita averiguar el esquema de base de datos perfecto por adelantado si su ORM puede ayudar a administrar los cambios en la estructura de la base de datos. Los cambios en la aplicación y la base de datos suelen ser lo mismo o están estrechamente relacionados, lo que ayuda a realizar un seguimiento de los cambios en la base de datos a medida que realiza cambios en el código.



Inconvenientes de los ORM

Los ORM no están exentos de defectos. En muchos casos, estos surgen de las mismas decisiones que hacen que los ORM sean útiles.

Uno de los problemas fundamentales de los ORM es el intento de ocultar los detalles del backend de la base de datos. Esta ofuscación hace que trabajar con ORM sea más fácil en casos simples o en escalas de tiempo pequeñas, pero a menudo genera problemas en el futuro a medida que crece la complejidad.

La abstracción nunca es 100 % completa e intentar usar un ORM sin comprender el lenguaje de consulta subyacente o la estructura de la base de datos a menudo conduce a suposiciones problemáticas. Esto puede dificultar o imposibilitar la depuración y el ajuste del rendimiento.

Quizás el problema más conocido de trabajar con ORM es el desajuste de la impedancia objeto-relacional, un término utilizado para describir la dificultad de traducir entre la programación orientada a objetos y el paradigma relacional utilizado por las bases de datos relacionales. Las incompatibilidades entre los modelos de datos utilizados por estas dos categorías de tecnología significan que es necesaria una abstracción imperfecta adicional con cada aumento en la complejidad. El desajuste de impedancia entre objetos y relaciones se ha denominado el Vietnam de la informática (en referencia a la Guerra de Vietnam) debido a su tendencia a aumentar la complejidad con el tiempo y conducir a situaciones en las que los caminos hacia el éxito o el cambio de rumbo son difíciles o imposibles.

En general, los ORM tienden a ser más lentos que las alternativas, especialmente con consultas complejas. Los ORM a menudo generan consultas complicadas para operaciones de bases de datos relativamente simples, porque emplean patrones generales que deben ser lo suficientemente flexibles para manejar otros casos. La confianza en el ORM para hacer lo correcto en todas las circunstancias puede conducir a errores costosos que pueden ser difíciles de detectar por adelantado.



Resumen de ORM

Los ORM pueden ser abstracciones útiles que facilitan mucho el trabajo con bases de datos. Pueden ayudarlo a diseñar e iterar rápidamente y salvar las diferencias conceptuales entre la lógica de la aplicación y las estructuras de la base de datos. Sin embargo, muchas de estas ventajas actúan como un arma de doble filo. Pueden impedirle comprender sus bases de datos y dificultar la depuración, el cambio de paradigmas o el aumento del rendimiento.




Glosario

Al trabajar con tecnologías que interactúan entre bases de datos y aplicaciones, es posible que encuentre alguna terminología con la que no esté familiarizado. En esta sección, repasaremos brevemente algunos de los términos más comunes que puede encontrar, algunos de los cuales se trataron anteriormente en este artículo y otros no.

  • Asignador de datos: Un asignador de datos es un patrón de diseño o una pieza de software que asigna estructuras de datos de programación a las almacenadas en una base de datos. Los mapeadores de datos intentan sincronizar los cambios entre las dos fuentes mientras las mantienen independientes entre sí. El propio mapeador es responsable de mantener una traducción funcional, lo que libera a los desarrolladores para iterar las estructuras de datos de la aplicación sin preocuparse por la representación de la base de datos.
  • Controlador de base de datos: Un controlador de base de datos es una pieza de software diseñada para encapsular y permitir conexiones entre una aplicación y una base de datos. Los controladores de base de datos abstraen los detalles de bajo nivel de cómo hacer y administrar conexiones y proporcionan una interfaz programática unificada para el sistema de base de datos. Por lo general, los controladores de base de datos son el nivel más bajo de abstracción que utilizan los desarrolladores para interactuar con las bases de datos, con herramientas de nivel superior que se basan en las capacidades proporcionadas por el controlador.
  • Ataque de inyección: Un ataque de inyección es un ataque en el que un usuario malintencionado intenta ejecutar operaciones de base de datos no deseadas utilizando una entrada especialmente diseñada en los campos de la aplicación de cara al usuario. A menudo, esto se usa para recuperar datos que no deberían ser accesibles o para eliminar o alterar información en la base de datos.
  • ORM: Los ORM, o mapeadores relacionales de objetos, son capas de abstracción que traducen entre las representaciones de datos utilizadas en las bases de datos relacionales y la representación en la memoria utilizada con la programación orientada a objetos. El ORM proporciona una interfaz orientada a objetos para los datos dentro de la base de datos, intentando reducir la cantidad de código y usar arquetipos familiares para acelerar el desarrollo.
  • Discordancia de impedancia objeto-relacional: El desajuste de impedancia objeto-relacional se refiere a la dificultad de traducir entre una aplicación orientada a objetos y una base de datos relacional. Dado que las estructuras de datos varían significativamente, puede ser difícil mutar y transcribir de forma fiel y eficaz las estructuras de datos programáticos al formato utilizado por el backend de almacenamiento.
  • Marco de persistencia: Un marco de persistencia es una capa de abstracción de middleware desarrollada para cerrar la brecha entre los datos del programa y las bases de datos. Los marcos de persistencia también pueden ser ORM si la abstracción que emplean asigna objetos a entidades relacionales.
  • Generador de consultas: Un generador de consultas es una capa de abstracción que ayuda a los desarrolladores a acceder y controlar las bases de datos al proporcionar una interfaz controlada que agrega funciones de usabilidad, seguridad o flexibilidad. Por lo general, los generadores de consultas son relativamente livianos, se enfocan en facilitar el acceso y la representación de datos, y no intentan traducir los datos a un paradigma de programación específico.
  • SQL: SQL, o lenguaje de consulta estructurado, es un lenguaje específico de dominio desarrollado para administrar sistemas de administración de bases de datos relacionales. Se puede utilizar para consultar, definir y manipular datos dentro de una base de datos, así como sus estructuras organizativas. SQL es omnipresente entre las bases de datos relacionales.


Conclusión

En este artículo, echamos un vistazo a algunas opciones diferentes para interactuar con su base de datos desde su aplicación. Examinamos los diferentes niveles de abstracción y la flexibilidad que ofrece el uso de lenguajes de consulta nativos de la base de datos como SQL, usando un generador de consultas para ayudar a elaborar consultas de forma segura y ORM para proporcionar un nivel de abstracción más completo.

Cada uno de estos enfoques tiene sus usos y algunos pueden ser más adecuados para ciertos tipos de aplicaciones que otros. Es importante comprender los requisitos de su aplicación, el conocimiento de la base de datos de su organización y los costos de las abstracciones (o la falta de ellas) que elija implementar. En general, comprender cada enfoque le dará la mejor oportunidad de seleccionar la opción que mejor se adapte a sus proyectos.