:::: MENU ::::

Magento y el modelo de datos EAV

Magento y el modelo de datos EAV
4 votos, 4.25 media (80% puntos)

Sin duda es el talón de aquiles de Magento, y la base de muchos de los problemas que impiden que explote como la plataforma de comercio electrónico definitiva: el modelo de base de datos EAV y su rendimiento.

De todos es conocido a estas alturas que Magento es una plataforma que devora los recursos de cualquier servidor. Incluso en servidores virtuales sin una configuración adecuada, la carga de las páginas puede eternizarse y el uso del panel de gestión ser una pesadilla.

Una gran parte de estos problemas de rendimiento es el mencionado modelo EAV (Entity Value Attribute).

En los siguientes párrafos intentaré explicar las diferencias entre el modelo de base de datos relacional (típico en otras plataformas de comercio electrónico) y el modelo de base de datos EAV adoptado por Magento.

Para ello, intentaremos extraer de la base de datos de dos plataformas (Magento y Prestashop), el nombre de un cliente y su dirección postal a partir de su identificador de cliente en la base de datos.

El objetivo no es extraer el nombre mediante las funciones del API de cada una de las plataformas, sino analizar la estructura de la base de datos para saber el trabajo que deben realizar esas funciones y así poder explicar la diferencia de rendimiento.

El modelo de datos tradicional: modelo relacional

Para extraer de la base de datos el nombre de un cliente en Prestashop, sólo debemos ir a la tabla ps_customer, que presenta la siguiente estructura:

Tabla de la base de datos de Prestashop

A partir del identificador de cliente, sólo es necesario realizar una consulta simple como:

SELECT firstname, lastname FROM ps_customer WHERE id_customer = '1'

Si queremos extraer también la dirección, debemos acudir también a la tabla ps_address, donde se encuentran almacenadas todas las direcciones.

SELECT
  c.firstname,
  c.lastname, a.*
FROM
  ps_customer c,
  ps_address a
WHERE
  c.id_customer = a.id_customer AND
  c.id_customer = '1'

Sencillo, ¿no?. Lo es porque en el modelo relacional cada tabla representa la información necesaria de un objeto, modelo o entidad (como prefieras llamarlo). Así, la tabla ps_customer define los datos básicos de un cliente y la tabla ps_address define los datos de una dirección.

Para indicar que una dirección pertenece a un cliente, en ambas tablas aparece un identificador común (el identificador del cliente), que las relaciona.

Base de datos Relacional de Prestashop

El modelo de base de datos de Magento: modelo EAV

El modelo EAV es en general mucho más flexible, ya que por ejemplo, el número y tipo de campos que definen un cliente no está fijado a priori, como en el caso relacional, donde dichos campos vienen establecidos por las ‘columnas’ de la tabla.

En el modelo EAV, los campos que definen cada entidad (en este caso a un cliente) también están almacenados en la propia base de datos.

Lo primero que debemos hacer en el modelo EAV es identificar donde se almacena la definición de un cliente. Para ello, en Magento deberemos recurrir a la tabla eav_entity_type y comprobar lo siguiente:

Tabla de entidades en Magento

Obtenemos un identificador de la definición de cliente (entity_type_id:1) y una tabla donde se guarda su información (customer/entity).

Vayamos entonces a la tabla customer_entity y veamos su estructura:

Tabla base de la entidad Cliente en Magento

No, parece que de aquí no vamos a obtener el nombre del cliente… ¿que está pasando?. Si nos fijamos, la tabla customer_entity, tiene otras tablas similares cerca, en este caso:

  • customer_entity
  • customer_entity_datetime
  • customer_entity_decimal
  • customer_entity_int
  • customer_entity_text
  • customer_entity_varchar

Ninguna de ellas parece que pueda ayudarnos a obtener el nombre del cliente tampoco, o al menos sus nombres no parecen indicar mucho.

Como hemos dicho, el modelo EAV guarda la definición de las entidades en la propia base de datos. Al consultar directamente la tabla customer_entity, nos hemos saltado un paso, que es saber en que tabla se encuentra el nombre del usuario (si es que existe, que todavía no lo sabemos).

Para saber en que tabla mirar, debemos acudir a otras dos tablas de información global de Magento: eav_entity_attribute y eav_attribute. Para no alargar mucho el tema nos saltaremos la primera de ellas, y viendo directamente la segunda, veremos algo como lo siguiente.

Vemos una serie de registros que tienen entity_type_id = 1 (hace un rato vimos que este identificador corresponde a la definición de cliente). En concreto: nombre, apellido, email, password, envío y facturación. Parece, efectivamente, que esos datos pueden formar parte de lo que define a un cliente (y efectivamente lo es).

Si nos fijamos en el registro ‘firstname’, vemos que además existen otros dos datos relevantes:

attribute_id = 1
backend_type = varchar

Mas arriba en este mismo artículo, listábamos las tablas relacionadas con los datos de los clientes. Casualmente vemos una tabla denominada customer_entity_varchar… sospechoso…

Vayamos a esa tabla y comprobemos su contenido.

Contenido de la tabla customer_entity_varchar en Magento

Bingo! Parece el nombre del cliente. Si vemos las columnas marcadas, vemos que entity_type_id corresponde con el tipo de entidad que buscamos (cliente), attribute_id corresponde con el atributo que buscamos (nombre) y entity_id es el identificador único del cliente (similar a la columna id_customer en el ejemplo de Prestashop).

Resumiendo, hemos tenido que buscar en 4 tabla para extraer el nombre del cliente.

SELECT
a.entity_type_id,
a.attribute_id,
et.entity_type_code,
a.attribute_code,
a.backend_type
FROM
eav_entity_type et,
eav_attribute a,
eav_entity_attribute ea
WHERE
et.entity_type_code = 'customer' AND
a.attribute_code = 'firstname' AND
et.entity_type_id = ea.entity_type_id AND
et.entity_type_id = a.entity_type_id AND
ea.attribute_id = a.attribute_id

Y con esto obtenemos algo de información útil

Resultado parcial para buscar el nombre de un cliente en Magento

Pero no el nombre del cliente. Para ello necesitaremos realizar otra nueva consulta, basada en los datos retornados por la primera.

SELECT
value
FROM
customer_entity_varchar
WHERE
entity_type_id = '1' AND
attribute_id = '1' AND
entity_id = '2'

Podríamos seguir profundizando, pero creo que hasta aquí es suficiente para valorar la diferencia en la complejidad de una y otra bases de datos.

¿Por qué EAV?

No pretendo establecer una crítica general al modelo EAV. El modelo es útil en determinadas circunstancias, pero tal vez esas circunstancias no correspondan con las necesidades de Magento.

El modelo EAV es útil cuando los atributos que definen a una entidad pueden ser muy variados, pero no se conocen todos los atributos de todas las entidades. Por ejemplo imaginemos que queremos definir a personas: deberíamos ser capaces de almacenar información como datos personales (nombre, apellidos, origen, fecha de nacimiento, etc), datos de contacto (dirección, teléfono, email, etc.), datos físicos (altura, peso, color de pelo, talla de zapatos, etc.), orientación política y religiosa, propiedades, datos financieros, laborales, etc.

Toda esa información debería tener cabida en la base de datos, pero no siempre podremos definir todas las características de cada persona.

En este caso el modelo EAV presenta la ventaja de la optimización de espacio, frente al modelo relacional.

Pero este no es el caso de Magento.

Conclusiones

Como hemos visto, el modelo EAV de la base de datos de Magento requiere del uso de hasta 4 tablas para obtener datos que en otros modelos se obtienen de forma directa. Además, las consultas son más complejas y se requiere del uso de resultados intermedios que ralentizan todavía más el proceso.

Por todo ello, y viendo el tipo de datos que se almacenan en una tienda online, el modelo EAV no es el adecuado para una plataforma como Magento, y de ello ya se han percatado los diseñadores de la misma, ya que desde hace un par de versiones, están creando un segundo modelo de datos (en paralelo) que a futuro dejará obsoleto el modelo EAV.

 




7 Comments

  • Responder rv |

    ¡Parece que estés describiendo el modelo de datos del ITS de esa empresa que tu y yo conococemos! (Con todos sus problemas)

    • Responder daniel |

      Ya te digo… ya lo decían mis profesores del ‘cole’…. antes de liarte a escribir código, mejor coge un papel y hazte cuatro diagramas, que si no, no harás mas que poner parches el resto del proyecto…

  • Responder GerBO |

    Me seria util ver otra propuesta que no sea de Magento, esto es debido a lo escrito por con aterioridad ” … En este caso el modelo EAV presenta la ventaja de la optimización de espacio, frente al modelo relacional. Pero este no es el caso de Magento….”, y que me ha dejado con esa inquietud, estoy tratando de desarrollar una BD EAV, pero diferente al contexto Magento. Saludos

  • Responder Pablo Lires |

    Estimado Daniel:
    Mi nombre es Pablo Lires, resido en Argentina y hace no mucho comencé a utilizar Magento.

    Ante todo felicitaciones por tu sitio, realmente entendi muchísimas cosas de Magento gracias a tu clara explicación.

    En esta ocasión estoy necesitando agregar dos atributos en el checkout (fecha y hora de entrega del producto), realmente hace mucho que estoy leyendo artículos y tutoriales pero lamentablemente no puedo avanzar.

    Si fueras tan gentil y si conoces algún tutorial para lograr realizar esta tarea te lo agradeceria muchísimo.

    Muchas gracias por tu tiempo y felicitaciones nuevamente por la calidad y profesionalismo de tu sitio.

  • Responder Héctor Alcántara Robles |

    Estimado Daniel, soy nuevo en Magento, aunque llego 20 años trabajando con bases de datos, sobre tod MS SQL, tu aportación me ha ayudado rapidamente a tener una idea clara del modelo.
    Agradezco mucho la misma y si algún día puedo devolverte el favor lo mio es MS SQL .Net

Hey! Qué opinas sobre el artículo?