Estoy pensando en usar un modelo de entidad-atributo-valor (EAV) para algunas de las cosas en uno de los proyectos, pero todas las preguntas al respecto en Stack Overflow terminan en respuestas que llaman a EAV un antipatrón.
Pero me pregunto si es así de malo en todos los casos.
Digamos que la entidad del producto de la tienda, tiene características comunes, como el nombre, la descripción, la imagen y el precio, que participan en la lógica de muchos lugares y tiene características (semi) únicas, como el reloj y la pelota de playa, que se describirían por aspectos completamente diferentes. Así que creo que EAV encajaría para almacenar esas características (semi) únicas.
Todo esto supone que, para mostrar la lista de productos, hay suficiente información en la tabla de productos (eso significa que no hay ningún EAV involucrado) y solo cuando se muestra un producto / se comparan hasta 5 productos / etc. Se utilizan los datos guardados con EAV.
He visto tal enfoque en el comercio de Magento y es bastante popular, entonces, ¿hay casos en que EAV es razonable?
Respuestas:
https://web.archive.org/web/20140831134758/http://www.dbforums.com/database-concepts-design/1619660-otlt-eav-design-why-do-people-hate.html
EAV le da flexibilidad al desarrollador para definir el esquema según sea necesario y esto es bueno en algunas circunstancias.
Por otro lado, funciona muy mal en el caso de una consulta mal definida y puede soportar otras malas prácticas.
En otras palabras, EAV te da suficiente cuerda para ahorcarte y en esta industria, las cosas deben diseñarse con el nivel más bajo de complejidad porque el tipo que te reemplaza en el proyecto probablemente sea un idiota.
fuente
En pocas palabras, EAV es útil cuando su lista de atributos crece con frecuencia, o cuando es tan grande que la mayoría de las filas se llenarían en su mayoría con NULL si convirtiera cada atributo en una columna. Se convierte en un antipatrón cuando se usa fuera de ese contexto.
fuente
CREATE TABLE
nuevo atributo?El uso de una estructura EAV tiene varias implicaciones que son compensaciones.
Está intercambiando un 'menos espacio para la fila porque no tiene 100 columnas que están
null
' en contra 'de consultas y modelos más complejos'.Tener un EAV generalmente significa que el valor es una cadena en la que se pueden introducir datos. Esto tiene implicaciones en la validez y la verificación de restricciones. Considere la situación en la que ha puesto la cantidad de baterías usadas como algo en la tabla EAV. Desea encontrar una linterna que use baterías de tamaño C, pero menos de 4 de ellas.
Lo que debe darse cuenta aquí es que no puede usar un índice razonablemente en el valor. Tampoco puede evitar que alguien ingrese algo que no sea un número entero allí, o un número entero no válido (usa baterías '-1') porque la columna de valor se usa una y otra vez para diferentes propósitos.
Esto tiene implicaciones al tratar de escribir un modelo para el producto. Tendrás los buenos valores mecanografiados ... pero también vas a tener una
Map<String,String>
sesión allí con todo tipo de cosas . Esto tiene implicaciones adicionales cuando se serializa a XML o Json y las complejidades de tratar de validar o realizar consultas en esas estructuras.Algunas alternativas o modificaciones al patrón a considerar es en lugar de una clave de forma libre, para tener otra tabla con claves válidas. Significa que, en lugar de hacer comparaciones de cadenas en la base de datos, está comprobando la igualdad de los identificadores de clave externa. Cambiar la clave en sí se realiza en un solo lugar. Tienes un conjunto de claves conocido, lo que significa que se pueden hacer como una enumeración.
También podría tener tablas relacionadas que contengan atributos de una clase específica de producto. Un departamento de abarrotes podría tener otra tabla que tenga varios atributos asociados que los materiales de construcción no necesitan (y viceversa).
Hay momentos que requieren especialmente una tabla EAV.
Considere la situación en la que no solo está escribiendo un sistema de inventario para su empresa donde conoce cada producto y cada atributo. Ahora está escribiendo un sistema de inventario para vender a otras compañías. No puede conocer todos los atributos de cada producto; deberán definirlos.
Una idea que surge es "vamos a dejar que el cliente modifican la mesa", y esto es sólo una mala (de entrar en meta-programación para las estructuras de tabla porque ya no sabe lo que es el lugar donde, que pueden regiamente desordenar la estructura o está dañado la aplicación, tienen acceso para hacer cosas incorrectas y las implicaciones de ese acceso se vuelven significativas). Hay más sobre esta ruta en MVC4: ¿Cómo crear un modelo en tiempo de ejecución?
En su lugar, crea la interfaz administrativa para una tabla EAV y permite que se use. Si el cliente desea crear una entrada para 'polkadots', entra en la tabla EAV y ya sabe cómo lidiar con eso.
Un ejemplo de esto se puede ver en el modelo de base de datos para Redmine , puede ver la tabla custom_fields y la tabla custom_values, que son partes del EAV que permiten extender el sistema.
Tenga en cuenta que si encuentra que toda la estructura de su tabla se parece a EAV en lugar de relacional, es posible que desee ver el sabor KV de NoSQL (cassandra, redis, Mongo, ...). Tenga en cuenta que a menudo vienen con otras compensaciones en su diseño que pueden o no ser apropiadas para lo que lo está utilizando. Sin embargo, están diseñados específicamente con la intención de una estructura EAV.
Es posible que desee leer SQL vs NoSQL para un sistema de gestión de inventario
Siguiendo este enfoque con una base de datos NoSQL orientada a documentos (couch, mongo), podría considerar que cada elemento del inventario es un documento en un disco ... extraer todo en un solo documento es rápido. Además, el documento está estructurado para que pueda extraer cualquier cosa rápidamente. Por otro lado, buscar en todos los documentos cosas que coincidan con un atributo particular puede tener un menor rendimiento (comparar usando 'grep' contra todos los archivos) ... todo es una compensación.
Otro enfoque sería LDAP, donde uno tendría una base con todos sus elementos asociados, pero luego también se le aplicarían clases de objetos adicionales para los otros tipos de elementos. (ver Inventario del sistema con LDAP )
Una vez que siga este camino, puede encontrar algo que coincida exactamente con lo que está buscando ... aunque todo viene con algunas compensaciones.
fuente
6 años despues
Ahora que JSON en Postgres está aquí, tenemos otra opción, para aquellos que usan Postgres. Si solo desea adjuntar algunos datos adicionales a un producto, entonces sus necesidades son bastante simples. Ejemplo:
Aquí hay una introducción más sencilla a JSON en Postgres: https://www.compose.com/articles/is-postgresql-your-next-json-database/ .
Tenga en cuenta que Postgres realmente almacena JSONB, no JSON de texto sin formato, y admite índices en campos dentro de un documento / campo JSONB, en caso de que descubra que realmente desea consultar esos datos.
Además, tenga en cuenta que los campos dentro de un campo JSONB no pueden modificarse individualmente con una consulta ACTUALIZAR; tendría que reemplazar todo el contenido del campo JSONB.
Es posible que esta respuesta no aborde directamente la pregunta, pero ofrece una alternativa a un patrón EAV, que debe ser considerada por cualquiera que esté reflexionando sobre la pregunta original.
fuente
jsonb_set()
función en Postgres 9.5 y posterior que es exactamente para esto. (El artículo que vinculó a los enlaces a su vez a un artículo más nuevo que discute las adiciones de la característica 9.5 .)Por lo general, las personas miran para otro lado si lo está utilizando para tablas de búsqueda u otras situaciones en las que el beneficio es evitar tener que crear tablas para uno o dos valores almacenados. La situación que está describiendo, donde básicamente está almacenando propiedades de elementos, suena perfectamente normal (y normalizada). Ampliar una tabla para almacenar un número variable de atributos de elementos es una mala idea.
Para el caso general de almacenar datos dispares en una tabla larga y delgada ... No debe tener miedo de crear nuevas tablas si es necesario, y tener solo una o dos tablas largas y delgadas no es mucho mejor que tener solo una o Dos mesas cortas y gordas.
Dicho esto, soy conocido por usar tablas EAV para iniciar sesión. Tienen alguna buena utilidad.
fuente
EAV cambia el problema de la estructura explícita a la percepción implícita. En lugar de decir que X es una tabla con las columnas A y B. Usted implica que las columnas A y B forman la tabla X. Es al revés en un sentido, pero no necesariamente hay un mapeo uno a uno. Se podría decir que A y B se asignan a la tabla (o tipo) X e Y. Esto podría ser importante en el dominio más involucrado donde el contexto es importante.
He estado estudiando Datomic para este tipo de enfoque y creo que es un sistema muy útil y poderoso con límites sobre lo que debe hacer con él (no es que no pueda).
Que EAV sería lento, o "darte suficiente cuerda para ahorcarte" no es una declaración con la que estoy de acuerdo. Más bien, pondría más énfasis en las fortalezas de EAV y si se adapta a su espacio problemático, debería considerarlo.
Mi experiencia es que es un maravilloso enfoque casi ilimitado para el modelado. Específicamente, en el caso de Datomic, imponen un conjunto semántico por encima de todo. Cualquier decisión de modelado que modele una relación puede ir libremente de una a muchas sin tener que rediseñar columnas / tablas. También puede retroceder siempre que la restricción no viole la invariante. Todo es lo mismo debajo del capó.
En mi opinión, el problema con EAV ha sido la falta de una implementación como Datomic. Dado que esta es una pregunta sobre EAV, no quiero hablar sobre Datomic, pero es una de esas cosas en las que creo que hicieron todo bien con respecto a EAV.
fuente