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.
fuente
Respuestas:
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.
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 .
fuente
¿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).
fuente
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.
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.
fuente
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.
fuente
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.
fuente
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 lo tanto, existe un retroceso del 100% si los objetos cambian, por lo que no podemos leer el bloque.
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.
fuente
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:
Entonces, si usas cualquier otro formato de serialización, obtienes una buena tienda Key-Value, si usas la serialización de Java obtienes desorden.
fuente
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 necesariosreadObject
yreadReplace
(para campos finales).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.
fuente