Mysql
 sql >> Base de données >  >> RDS >> Mysql

Dois-je placer les valeurs EAV dans une table de types de données ?

Franchement, la meilleure option est "pas EAV". Envisagez d'utiliser hstore champs, XML , ou json .

Dans PostgreSQL, il n'y a aucun avantage en termes de performances à utiliser des tables par type de données. NULL les valeurs sont stockées dans un NULL compact bitmap, cela fait donc très peu de différence si vous avez un tuple comme (NULL, NULL, NULL, 42, NULL, NULL) ou juste (42) .

Cela vous permet également d'ajouter CHECK contrainte imposant qu'exactement un champ doit être non-NULL , vous n'obtenez donc pas plusieurs valeurs de types différents.

Démo :

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)

Dans ce cas, le bitmap nul n'ajoute aucun espace, probablement en raison des exigences d'alignement.