sql >> Base de Datos >  >> RDS >> Mysql

¿Debo colocar valores EAV en una tabla de tipo de datos?

Francamente, la mejor opción es "no EAV". Considere el uso de hstore campos, XML o json .

En PostgreSQL, no hay ninguna ventaja de rendimiento en el uso de tablas por tipo de datos. NULL los valores se almacenan en un NULL compacto mapa de bits, por lo que hace muy poca diferencia si tiene una tupla como (NULL, NULL, NULL, 42, NULL, NULL) o simplemente (42) .

Esto también le permite agregar CHECK restricción que impone que exactamente un campo no debe ser NULL , para que no obtenga múltiples valores de diferentes tipos.

Demostración:

regress=> CREATE TABLE eav_ugh (
    entity_id integer,
    int_value integer,
    numeric_value numeric,
    text_value text,
    timestamp_value timestamp with time zone,
    CONSTRAINT only_one_non_null CHECK (
            (int_value IS NOT NULL AND numeric_value IS NULL AND text_value IS NULL AND timestamp_value IS NULL) OR
            (int_value IS NULL AND numeric_value IS NOT NULL AND text_value IS NULL AND timestamp_value IS NULL) OR
            (int_value IS NULL AND numeric_value IS NULL AND text_value IS NOT NULL AND timestamp_value IS NULL) OR
            (int_value IS NULL AND numeric_value IS NULL AND text_value IS NULL AND timestamp_value IS NOT NULL)
    )
);
CREATE TABLE
regress=> insert into eav_ugh (entity_id, numeric_value) select x, x from generate_series(1,5000) x;
INSERT 0 5000
regress=> select pg_relation_size('eav_ugh');                                           
 pg_relation_size 
------------------
           229376
(1 row)

regress=> CREATE TABLE no_null_cols(entity_id integer, numeric_value numeric);
CREATE TABLE
regress=> insert into no_null_cols (entity_id, numeric_value) select x, x from generate_series(1,5000) x;
INSERT 0 5000
regress=> select pg_relation_size('no_null_cols');
 pg_relation_size 
------------------
           229376
(1 row)

regress=> SELECT sum(pg_column_size(eav_ugh)) FROM eav_ugh;
  sum   
--------
 164997
(1 row)

regress=> SELECT sum(pg_column_size(no_null_cols)) FROM no_null_cols;
  sum   
--------
 164997
(1 row)

En este caso, el mapa de bits nulo no agrega ningún espacio, probablemente debido a los requisitos de alineación.