Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Soll ich EAV-Werte in eine Datentyptabelle einfügen?

Ehrlich gesagt ist die beste Option "nicht EAV". Sehen Sie sich die Verwendung von hstore an Felder, XML , oder json .

In PostgreSQL bringt die Verwendung von Tabellen pro Datentyp keinen Leistungsvorteil. NULL Werte werden in einem kompakten NULL gespeichert Bitmap, daher macht es kaum einen Unterschied, ob Sie ein Tupel wie (NULL, NULL, NULL, 42, NULL, NULL) haben oder einfach (42) .

Auf diese Weise können Sie auch CHECK hinzufügen Einschränkung, die erzwingt, dass genau ein Feld ungleich NULL sein muss , sodass Sie nicht mehrere Werte unterschiedlichen Typs erhalten.

Demo:

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)

In diesem Fall fügt die Null-Bitmap überhaupt keinen Platz hinzu, wahrscheinlich aufgrund von Ausrichtungsanforderungen.