El profesor nos dijo que almacenemos objetos Java serializados como blobs en lugar de definir tablas relacionales

21

En lugar de definir realmente tablas con los atributos correctos, mi profesor nos dijo que podríamos asignar objetos a identificadores como este:

id (int)  |   Serialized Object (blob)
   1               10010110110

Puedo ver tantos problemas con esto; redundancia de datos, tener que rastrear los identificadores por separado, tener que llevar toda la tabla a la memoria para buscar cualquier cosa, y ** si quiero cambiar mi modelo en el código Java ya no podré deserializar el blob almacenado en el base de datos en ese modelo.

O estoy atascado para siempre con ese modelo o tengo que hacer otras cosas realmente feas para cambiar mi modelo. ** Todo esto me parece una mala forma. ¿Estoy justificado en no estar de acuerdo con mi profesor? ¿Hay algún beneficio en hacer esto que no haya pensado? Si estoy en lo correcto, ¿debería decirle algo a mi profesor sobre esto? Estaba predicando esto a toda mi clase e incluso dijo que había construido proyectos de esa manera. Una segunda opinión sería genial.

El curso se llama Diseño de software .

Mi profesor no dijo que esta era la mejor manera, pero sí dijo que era una alternativa legítima a la definición de tablas relacionales.

El modelo no es dinámico de ninguna manera.

Tyler Davis
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Paul White dice GoFundMonica

Respuestas:

34
  1. No es, en sí mismo, algo malo, en absoluto. Discutir sobre "cuál es mejor" sin un contexto adecuado (= requisitos exactos) es un ejercicio inútil.

  2. La parte en negrita está mal. Puede ampliar fácilmente los objetos ya serializados para agregar nuevos campos y lograr una compatibilidad binaria completa con los objetos más antiguos. También puede simplemente crear nuevas clases en lugar de cambiar las originales.

Su discusión con el profesor debe enfocarse en los pros y los contras de "relacional" versus "almacén de valores clave" en diferentes escenarios, no en "mejoría" abstracta. O bien, podría tener una discusión sobre si la Navidad es superior al Día de Acción de Gracias.

- una edición, después de leer otras respuestas.

Una de las otras respuestas llega a afirmar que "es difícil imaginar un caso en el que los profesionales superen a los contras".

Debido a que toda la discusión debe ser sobre problemas concretos (de lo contrario, ni siquiera podemos definir "mejor" y "peor"), permíteme darte un ejemplo concreto. Está completamente inventado, pero traté de desarrollar tantos detalles como sea posible.

Imagine que tiene un sitio de juegos en línea, con una base de datos que almacena estadísticas de jugadores en diferentes juegos en línea (jugados en el navegador, escritos en GWT y compilados en JavaScript). Algunos de los juegos son estratégicos, algunos son juegos de acción, otros son plataformas. La base de datos es relacional y almacena jugadores e historial de jugadas y el puntaje.

Un día obtienes un requisito adicional: deja que los jugadores guarden el estado del juego en la nube, durante el juego, para que puedan reiniciar el juego más tarde, en el mismo punto. Huelga decir que la única razón para almacenar este estado temporal es volver al juego, el estado en sí mismo nunca será introspectado.

Ahora tiene dos opciones básicas:

  • Como los juegos están escritos en Java, puede tomar el modelo con bastante facilidad, enviarlo al servidor, serializarlo en una línea de código y almacenarlo como un blob. La mesa se llamará "salvado_juegos" y tendrá claves foráneas para el jugador, etc. Desde el punto de vista de la base de datos, un "juego guardado" es un blob opaco e indivisible.

  • puedes crear un modelo relacional separado para cada uno de tus 100 juegos (esto será decenas de mesas por juego). Solo para pacman, por ejemplo, tendrá que tener una mesa que almacene las posiciones de todos los gránulos, bonificaciones, posiciones y estado actual de los fantasmas no consumidos. Si alguien, algún día, modifica el juego, aunque sea un poco, tendrá que actualizar el modelo relacional. Además, para cada tipo de juego, deberá implementar una lógica para escribir el modelo Java en la base de datos y volver a leerlo.

La respuesta de Justin Cave dice que debes elegir la segunda opción. Creo que esto sería un gran error.

Además, tengo el presentimiento de que la percepción de Justin Cave es que lo que presenté arriba es un caso de "borde" o "raro". Creo que a menos que pueda presentar algún tipo de datos duros (basado en una muestra representativa de todos los proyectos de TI en el mundo, no solo, por ejemplo, aplicaciones empresariales en los EE. UU.), Consideraré esa opinión como un caso clásico de una proyección parcialidad.

En realidad, el problema de los objetos Java serializados en una base de datos relacional es mucho más profundo de lo que parece. Toca el núcleo mismo del 1NF, a saber, ¿cuál es el dominio de un atributo? . Si está realmente interesado en el tema, hay un gran artículo de CJ Date, en su Fecha en la base de datos: Escritos 2000-2006 .

fdreger
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Paul White dice GoFundMonica
22

¿Pueden (y lo hacen) las personas entregar con éxito proyectos que hacen este tipo de cosas? Desafortunadamente, sí, lo hacen razonablemente a menudo.

¿Es este un buen enfoque? No, no es. Básicamente, está tomando su base de datos relativamente cara y convirtiéndola en un sistema de archivos relativamente lento. Si realmente desea construir un sistema que guarde su estado serializando y des serializando objetos, también puede usar un sistema de archivos en lugar de una base de datos.

Si crea sistemas que almacenan datos serializando objetos en la base de datos, no se hará amigo de su DBA. Terminarás almacenando datos redundantes. Terminará con datos terriblemente inconsistentes: cada vez que se actualizan datos compartidos, algunos objetos terminarán con los nuevos valores y algunos objetos terminarán con los valores antiguos. Hará que sea imposible hacer cualquier tipo de informe sobre los datos; todo lo que cualquiera quiera hacer con los datos requerirá que alguien escriba código adicional. Ese es un gran problema en la mayoría de las empresas porque quieren hacer cosas como extraer datos de un sistema para cargar en otro sistema o tener un sistema de informes que pueda entregar informes de múltiples aplicaciones front-end. Además, como usted señala, tendrá que lidiar constantemente con problemas cuando '

¿Hay ventajas en este enfoque? Supongo que puedes argumentar que es bastante fácil implementar la primera versión de la aplicación. Y le permite al desarrollador ignorar por completo todo lo relacionado con la interacción adecuada con una base de datos. Me cuesta imaginar muchos casos en los que estas ventajas superen las numerosas desventajas del enfoque.

En cuanto a cómo debe tratar con este profesor en particular, ese es un tema separado (y que probablemente esté fuera del alcance de este foro). Si su profesor está desarrollando proyectos activamente en el mundo real, probablemente no será terriblemente receptivo a cualquier argumento de un estudiante de que su enfoque es fundamentalmente incorrecto (incluso si el enfoque es realmente fundamentalmente incorrecto). Es mejor que haga su proyecto de la manera que el profesor quiera y que aprenda la forma correcta de guardar datos por su cuenta (o en un curso diferente).

Justin Cave
fuente
2
Lo que dijiste, más mis dos centavos. La reutilización se trata de modularidad y compartir. El modelo de objetos se centra en compartir objetos y reutilizar código. El modelo de base de datos se centra en compartir y reutilizar datos. Ninguno de los modelos es completamente imbécil. Ninguno de los modelos es la perfección. Y es muy, muy difícil conciliar los dos.
Walter Mitty
1
Estoy de acuerdo con esto, pero odio ver a un profesor enseñar algo y decir que es mejor sin ser confrontado. ¿Qué pasa con todos los otros estudiantes pobres en la clase que irán al mundo real pensando que esta es la forma correcta?
Kevin
Seguro. Esta formulación equivale a objetos que fingen ser datos. Y son datos, pero no datos muy útiles.
Walter Mitty
La ventaja casi siempre desaparece tan pronto como desee lanzar v2 de su aplicación.
Andy
10

Hay situaciones en las que este tipo de diseño es sensato, sin que usted describa de qué se tratan sus proyectos y cómo se utiliza, es difícil decir si esto es apropiado o no.

Su DBA puede odiarlo si almacena BLOB, pero en muchas situaciones la única otra alternativa es convertir las tablas en Entity-attribute-value, que obtiene aún más odio de los DBA. La otra alternativa es utilizar bases de datos no relacionales, generalmente bases de datos basadas en objetos o en diccionarios o una base de datos orientada a documentos, que algunos DBA, especialmente aquellos que solo conocen relaciones, odiarían con aún más pasión. Sin embargo, la base de datos no relacional tiene sus propios problemas con los que lidiar, sin duda puede ser el caso que el uso de la base de datos de objetos para almacenar objetos exponga otros problemas que habría podido resolver fácilmente en los sistemas relacionales.

¿Hay algún beneficio en hacer esto que no haya pensado?

Almacenar objetos serializados significa que puede almacenar datos sin esquemas (tenga en cuenta que, a pesar del nombre, sin esquemas generalmente no significa que en realidad no haya ningún esquema, sino que solo hay un esquema implícito). Hay muchos dominios problemáticos en los que no es posible definir el esquema antes de tiempo en el momento del desarrollo, y donde seguir el diseño tradicional de la base de datos relacional significaría que tiene que alterar el esquema de la base de datos cada dos semanas, o que termine con una tabla que tiene El 80% de las columnas que no se utilizan el 80% del tiempo, o cientos de tablas diferentes para almacenar lo que realmente son los mismos datos, ninguno de los cuales indica un buen diseño. La raíz de este problema generalmente se debe a que obliga a ajustar un dominio de problema no relacional en una base de datos relacional.

Por supuesto, hay muchos proyectos en los que las personas piensan que necesitan usar EAV, sin esquemas o blob store que causa innecesariamente lo que hubiera sido un dolor evitable. Definitivamente deberías discutir con tu profesor cuál es su razonamiento y presentar tus propios argumentos; escuche los argumentos y prepárese para que pueda llegar a estar de acuerdo con él o no, tal vez esté equivocado.

Lie Ryan
fuente
7

He hecho esto antes; es una técnica útil en ciertos escenarios, sin embargo, depende del formato de serialización utilizado. Si hago esto, me aseguro de usar un formato de serialización que me permite desaserializar versiones anteriores de mi modelo (por ejemplo, XML).

Normalmente lo usaría en escenarios donde el formato de datos daría como resultado un modelo relacional complicado que no ofrece ventajas (por ejemplo, cuando los requisitos comerciales no requieren ningún filtrado, etc.) y ya estoy usando una base de datos (para otros datos relacionales). Uno de esos casos era una aplicación que tenía consultas de los usuarios: el modelo relacional tenía un puñado de tablas para almacenar cosas como condiciones, condiciones anidadas (OR / AND, etc.), opciones de clasificación, etc. Era bastante complicado y cuando necesitábamos agregar una nueva característica que requería un cambio en la base de datos. Reemplacé todo con una sola tabla de consultas con un blob serializado que representa todas las demás opciones.

Otro caso fue un sistema que procesaba varios "trabajos". Había varios tipos diferentes de trabajos y cada trabajo tenía parámetros diferentes, sin requisitos comerciales para poder buscar / filtrar trabajos basados ​​en esos parámetros. Almacenar esto como una base de datos relacional habría requerido al menos 1 nueva tabla por tipo de trabajo, lo que dificulta agregar nuevos tipos de trabajo. En cambio, los parámetros se almacenan como un blob en la base de datos: cada tipo de trabajo es responsable de la serialización y la deserialización de sus propios parámetros.

No es muy frecuente que se encuentre con escenarios como este, sin embargo, de vez en cuando surge una situación como la anterior donde la serialización de datos de blob le ahorra una gran cantidad de esfuerzo, hace que su aplicación sea más fácil de mantener y no tiene desventajas reales.

Justin
fuente
6

Justin Cave tiene razón en que esto puede conducir a datos redundantes, pero esto realmente depende de cómo diseñe su base de datos.

El enfoque de serializar un objeto completo en una gota no es tan escandaloso como la mayoría de las personas aquí piensan que es. De hecho, para algunas aplicaciones, este puede ser el mejor diseño que puede hacer, como lo expliqué aquí: /programming//a/12644223/1121352 .

De hecho, serializar un objeto conlleva al menos dos beneficios:

1- Reducción de la falta de coincidencia de impedancia : algunos tipos de Java simplemente no están disponibles en SQL, particularmente si usa muchas clases y tipos personalizados, por lo tanto, la conversión de objetos Java a SQL puede ser una molestia enorme e incluso generar ambigüedades.

2- Más flexibilidad en tu esquema . De hecho, los esquemas relacionales son realmente excelentes para los datos que comparten la misma estructura, pero si algunos de sus objetos dentro de una sola clase pueden tener diferentes propiedades dependiendo de las condiciones en tiempo de ejecución, los esquemas relacionales pueden obstaculizar significativamente su flujo de trabajo.

Por lo tanto, ciertamente hay beneficios para este enfoque (al menos estos dos, pero ciertamente otros que no cité), pero, por supuesto, el gran costo a pagar es que pierde casi todos los beneficios de los esquemas relacionales.

Sin embargo, puede obtener lo mejor de ambos mundos si diseña cuidadosamente su base de datos: aún puede establecer un esquema relacional (es decir, columnas de clave únicas) utilizando los atributos que son únicos para cada objeto, y luego almacenar el objeto en el blob . De esta manera, aún puede garantizar la recuperación rápida de su objeto dado un identificador único que está definido por los atributos de su objeto, lo que también reduce la redundancia, mientras aniquila la falta de coincidencia de impedancia y mantiene la flexibilidad total de los objetos Java.

Como nota al margen, algunos fabricantes de bases de datos intentan mezclar modelos relacionales y de objetos, como el tipo de datos JSON en PostSQL y PostgreSQL para que pueda procesar directamente JSON como cualquier columna relacional, y también SQL3 y OQL (Object Query Language) para agregar objetos (limitados) a SQL.

Al final, todo esto es una cuestión de diseño y compromiso entre el modelo relacional y el modelo de objetos.

/ EDITAR después de leer los comentarios: por supuesto, si sus datos deben ser buscables ("consultables"), NO debe almacenar sus datos como un blob. Pero si algunas partes de sus datos no deben buscarse , sino más bien algún tipo de metadatos, entonces almacenar esta parte de datos como un objeto dentro de un blob puede ser una buena solución, especialmente si estos metadatos tienen una estructura flexible y puede cambiar de un objeto a otro.

gaborous
fuente
5

Pongamos un ejemplo práctico de cuándo lo hice en el pasado.

Tenemos una base de datos que contiene todos los datos para una aplicación de usuario muli; la base de datos también tiene una tabla de usuarios con sus derechos de acceso. Todos estos datos se normalizan como se esperaba.

Luego, solicitamos que la aplicación recuerde qué ventanas había abierto un usuario y qué estaba haciendo, para que pueda restaurar el estado cuando el usuario comienza a trabajar a la mañana siguiente.

  • En primer lugar, si esto a veces falla, ¿no es impertinente?

    • Por ejemplo, si la primera vez que alguien usa una nueva versión de la aplicación, olvida las ventanas que tenía abiertas, entonces qué ...
  • Por lo tanto, existe un retroceso del 100% si los objetos cambian, por lo que no podemos leer el bloque.

  • Ya tenemos una base de datos centralizada con control de acceso, respaldo, etc.
  • El costo de almacenar los datos en archivos es alto, ya que los archivos deberán colocarse en algún tipo de servidor de archivos al que tengan acceso todas las máquinas de usuario, o deberá escribirse una API para leer estos archivos.

En otra ocasión , teníamos una aplicación que hacía muchos cálculos de larga duración y los usuarios deseaban poder reiniciar los cálculos desde el último punto bueno si hubo un corte de energía, etc. No hay forma de que una versión diferente de se podría esperar que las aplicaciones reiniciaran los cálculos, y como había muchos objetos que debían guardarse, la normalización de los datos habría sido costosa.

Debido a que la base de datos ya está en su lugar y se usa para los datos de aplicación normalizados bien definidos, y no hay una razón real para no usarla para almacenar los blogs, tomamos la opción sensata y rápida.

Ian Ringrose
fuente
4

Un factor muy importante: la serialización de Java (una que se habilita mediante la implementación Serializable) es un formato muy malo en sí mismo, por lo que realmente no debería usarlo para el almacenamiento permanente de objetos.

Los inconvenientes de la serialización de Java incluyen:

  • Los datos no son realmente legibles desde otros idiomas.
  • No es muy fácil mantener la compatibilidad hacia adelante de los objetos serializados, es decir: si agrega (o elimina) campos a la clase, no es tan fácil leer los objetos creados por una versión anterior de la clase.
  • No es tan rápido (pero su kilometraje puede variar)

Entonces, si usas cualquier otro formato de serialización, obtienes una buena tienda Key-Value, si usas la serialización de Java obtienes desorden.

jb.
fuente
Los hechos en la respuesta son simplemente falsos: 1) el formato está cubierto por una especificación exhaustiva; 2) agregar campos no es un problema en absoluto, el formato es muy flexible; 3) la velocidad depende de los datos reales, pero es comparable (a veces más rápido, a veces más lento) a formatos como JSON o XML. Básicamente, la respuesta completa es incorrecta, excepto una línea: "los datos no son realmente legibles desde otros idiomas".
fdreger
1
Aparte de 1)que estaba equivocado, el resto de la respuesta es IMO válida. Si desea tener control sobre deserialisaton, que es necesario cuando agrega / elimina campos (y especialmente cuando tiene campos finales), las interfaces parecen torpes, y necesita anular más métodos que son necesarios readObjecty readReplace(para campos finales).
jb.
Estás equivocado, agregar y eliminar campos no requiere escribir ningún método. En cuanto a los campos finales: su respuesta original no los menciona en absoluto, y si lo hiciera, sería irrelevante (el problema sería común para todos los demás formatos). Finalmente, decir "No es tan rápido (pero su millaje puede variar)" simplemente no significa nada. Solo tienes un hecho correcto: el de otros idiomas. Esa es una base muy débil para llamar a algo "un desastre".
fdreger
1
Agregar campos no requiere que escriba ningún método, pero si desea influir en cómo se deserializan, debe especificar ese comportamiento. Trataré de desenterrar algunas referencias a problemas con la deserialización del esquema de objetos en evolución.
jb.
3

Este es un hilo interesante con algunas respuestas bien pensadas. Al no estar familiarizado con todas las implicaciones de almacenar y recuperar objetos serializados, creo que sería interesante proporcionar la respuesta que podría dar a un equipo de DBA o equipo de desarrollo:

La clave es cumplir con los requisitos actuales y futuros, y mantener la solución lo más simple posible para minimizar el trabajo de soporte futuro. Deben cumplirse tanto los requisitos funcionales como los requisitos no funcionales (por ejemplo, infraestructura y base de datos). Recuerda la regla 80/20. Comprenda la importancia de la aplicación para el negocio y qué esfuerzo de desarrollo es apropiado.

No se obsesione con el espacio de la base de datos, la velocidad y la memoria si no son problemas.

Si un DBMS está en su lista aprobada, puede usarlo en una solución siempre que los costos sean apropiados. No hay ningún problema al usar una base de datos relacional para almacenar blobs simples, especialmente si esto simplifica las cosas.

Si la solución es ser un prototipo o una etapa / versión temprana, se debe poner aún más énfasis en mantener las cosas simples. Siempre puede extender el esquema de datos más adelante siempre que lo planifique.

Recuerde que las bases de datos relacionales no imponen integridad o consistencia a menos que el esquema cubra un área comercial autónoma y las reglas comerciales sean estrictas. (por ejemplo, la solución a la Pregunta del objeto serializado puede considerar un diccionario / diccionario de ontología para hacer cumplir las reglas).

Vale la pena considerar que todas las bases de datos relacionales no usan esquemas de bases de datos relacionales puros (por ejemplo, estrellas, espaciales, no relacionales ...), también las aplicaciones pueden usar bases de datos relacionales como almacenes no relacionales, como en la pregunta. Muchas bases de datos comerciales centrales funcionan de esta manera.

Dave
fuente