database database-design postgresql entity-attribute-value

database - Es EAV-Híbrido una mala elección de diseño de base de datos



database-design postgresql (4)

Tenemos que rediseñar una base de datos POI heredada de MySQL a PostgreSQL. Actualmente, todas las entidades tienen atributos 80-120 + que representan propiedades individuales.

Se nos ha pedido que consideremos la flexibilidad y un buen enfoque de diseño para la nueva base de datos. Sin embargo, el nuevo diseño debe permitir:

  • n no de atributos / propiedades para cualquier entidad, es decir, ninguno de los atributos para ninguna entidad no son fijos y pueden cambiar de forma regular.

  • Permita que los administradores de contenido agreguen nuevas propiedades a las entidades existentes sobre la marcha utilizando interfaces de administración en lugar de hacer cambios en el esquema de la base de datos todo el tiempo.

Hay bastantes discusiones sobre los problemas de rendimiento de EAV, pero si no vamos con un EAV híbrido, terminamos:

  • tener muchas columnas vacías (todavía vamos y agregamos nuevas columnas incluso si el 99% de los datos no tienen esas propiedades)
  • pasar más tiempo manteniendo la base de datos esp. cuando los atributos siguen cambiando.
  • no hay forma de permitir que los administradores de contenido agreguen nuevas propiedades a las entidades existentes

De todos modos, esto es lo que estamos pensando sobre el nuevo diseño (ERD básico incluido):

  • Tenga tablas separadas para cada entidad que contengan alguna información básica que sea exclusiva, por ejemplo, id, nombre, dirección, contacto, creado, etc., etc.

  • Tiene 2 tablas tipo de atributo y atributo para almacenar información de propiedades.

  • Vincule cada entidad a un atributo utilizando una relación de muchos a muchos.

  • Almacene direcciones en diferentes tablas y enlace a entidades usando clave externa.

Creemos que esto nos permitirá ser más flexibles al agregar, eliminar o actualizar propiedades.

Sin embargo, este diseño dará como resultado un mayor número de uniones cuando se recuperen datos, por ejemplo, para mostrar todos los "atributos" de un estadio determinado, podríamos tener una consulta con más de 20 combinaciones para obtener todos los atributos relacionados en una sola fila.

¿Qué piensa sobre este diseño y cuál sería su consejo para mejorarlo?

Gracias por leer.


Básicamente, EAV está intentando implementar una base de datos dentro de una base de datos y lleva a la locura. Las consultas para extraer datos se vuelven demasiado complejas, y sus datos no tienen un modelo estable y específico para mantenerlos en algún tipo de orden.

He escrito sistemas EAV para aplicaciones limitadas, pero como una solución genérica suele ser una mala idea.


EAV puede ser útil para algunos escenarios. Pero es un poco como "el lado oscuro". Potente, flexible y muy seductora es. Pero es algo de una salida fácil. Una manera fácil de hacer un análisis y diseño adecuado.

Creo que "entidad" es un poco exagerado demasiado general. Parece que tienes alguna idea de lo que debería estar conectado a esa entidad, como la dirección y el contacto. Qué pasa si decides tener "Libros" en el modelo. ¿Tendrían también direcciones y contactos? Creo que deberías intentar encontrar las generalizaciones correctas y mantener las partes del modelo de EAV a un mínimo. Siempre que quiera mostrar un cierto subconjunto de atributos, o probar la existencia del valor, o determinar el comportamiento en función del valor, realmente debería tenerlo modelado como columnas.

No tendrá una mejor oportunidad de diseñar este sistema que ahora. Los requisitos se conocen desde la versión anterior, y también qué funcionó y qué no. (Simplemente no seas víctima del segundo efecto del sistema )


Mantengo un sistema de 10 años que tiene un modelo central de EAV con más de 10 millones de entidades, 500 millones de valores y cientos de atributos. Algunas consideraciones de diseño de mi experiencia:

Si tiene alguna lógica de negocios que se aplique a un atributo específico, vale la pena tener ese atributo como una columna explícita. Los atributos de EAV deberían ser realmente cosas que sean genéricas, la aplicación no debe distinguir el atributo A del atributo B. Si encuentra una referencia literal a un atributo de EAV en el código, es probable que sea una columna explícita.

Tener cantidades significativas de columnas vacías no es un gran problema técnico. Necesita buenas prácticas de codificación y documentación para compartimentar las diferentes inquietudes que terminan en una tabla:

  • Tenga convenciones y reglas que le permitan saber qué parte de su aplicación lee y modifica qué parte de los datos.
  • Utilice vistas para facilitar la búsqueda en la base de datos con herramientas de depuración.
  • Cree y mantenga generadores de datos de prueba para que pueda crear fácilmente datos ficticios que cumplan con el esquema para las partes del modelo en las que no está interesado actualmente.
  • Utilice la versión de base de datos rigurosa. La única forma de realizar cambios de esquema debe ser a través de una herramienta que realice un seguimiento y aplique los scripts de cambio. Postgresql tiene un DDL transaccional, que es una característica fundamental para automatizar los cambios de esquema.

A Postgresql no le gustan las mesas delgadas. Cada valor de atributo genera una sobrecarga de almacenamiento de datos de 32 bytes, además del trabajo adicional de atravesar todas las filas para reunir los datos. Si principalmente lee y escribe los atributos como un lote, considere la posibilidad de serializar los datos en la fila de alguna manera. attr_ids int[], attr_values text[] es una opción, hstore es otra, o algo del lado del cliente, como json o protobuf, si no necesita tocar nada específico en el lado de la base de datos.

No te esfuerces en poner todo en una sola tabla de entidades. Si no comparten ningún atributo de manera sensata, use múltiples instancias del patrón de EAV específico que usa. Pero trate de usar el mismo patrón y comparta cualquier código de acceso entre las diferentes instancias. Siempre puedes parametrizar el código en el nombre de la entidad.

Siempre tenga en cuenta que el código es información y la información es código. Debe encontrar el equilibrio correcto entre las decisiones de inserción en el metamodelo y expresarlas como código. Si hace que el metamodelo haga demasiado, modificarlo necesitará el mismo tipo de capacidad para entender el sistema, las herramientas de control de versiones, los procedimientos de control de calidad y la puesta en escena de su código, pero no tendrá ninguna de las herramientas. En esencia, estarás haciendo la programación en un lenguaje no estándar muy torpe. Por otro lado, si deja demasiado en el código, cada cambio trivial necesitará una nueva versión de su software. Las personas tienden a equivocarse al hacer que el metamodelo sea demasiado complejo. Crear herramientas de desarrollador para los metamodelos es un trabajo arduo y tedioso y tiene un beneficio limitado. Por otro lado, hacer que el proceso de publicación sea más barato automatizando todo lo que sucede desde el compromiso hasta la implementación tiene muchos beneficios secundarios.


Una buena implementación de EAV se puede encontrar en magento, un cms para comercio electrónico. Hay mucha mala conversación sobre EAV en esos días, pero desafío a cualquiera a encontrar otra solución que no sea EAV para tratar con atributos de productos infinitos.

Seguro que puedes enumerar todas las columnas que necesitarías para cada producto en el mundo, pero eso te tomaría mucho tiempo e inevitablemente olvidarías los atributos del producto en el camino.

Entonces, la conclusión es: use EAV para infinitas cosas, pero no confíe en EAV para todas las tablas de la base de datos. Por lo tanto, un EAV híbrido y un db relacional, cuando se hacen correctamente, son una herramienta poderosa que no se puede lograr utilizando solo columnas fijas.