问题
Let's say I'm building a website about cars. The car entity has a lot of enum-like attributes:
- transmission (manual/automatic)
- fuel (gasoline/diesel/bioethanol/electric)
- body style (coupe/sedan/convertible/...)
- air conditioning (none/simple/dual-zone)
- exterior color (black/white/gray/blue/green/...)
- interior color (black/white/gray/blue/green/...)
- etc.
The list of these attributes is likely to change in the future. What is the optimal way to model them in the database? I can think of the following options but can't really decide:
- use fields in the
car
table with enum values- hard to add more columns later, probably the fastest
- use fields in the
car
table that are foreign keys referencing a lookup table- hard to add more colums later, somewhat slower
- create separate tables for each of those attributes that store the possible values and another table to store the connection between the car and the attribute value
- easy to add more possible values later, even slower, seems to be too complicated
回答1:
Depending upon the number of queries and size of the databases you could either:
- Make wide tables
- Make an attibutes table and a car_attributes table where: cars -> car_attributes -> attributes
#1 will make faster, easier queries due to less joins, but #2 is more flexible
回答2:
Idealy is to create a relational database. Each table from DB should be represented by a class, as in hibernate. You should make 2 tables for the car. One for the interior and one for the exterior of the car. If you want to add extra features, you just add more columns.
回答3:
Now here is a (very basic) EAV model:
DROP TABLE IF EXISTS example.zvalue CASCADE;
CREATE TABLE example.zvalue
( val_id SERIAL NOT NULL PRIMARY KEY
, zvalue varchar NOT NULL
, CONSTRAINT zval_alt UNIQUE (zvalue)
);
GRANT SELECT ON TABLE example.zvalue TO PUBLIC;
DROP TABLE IF EXISTS example.tabcol CASCADE;
CREATE TABLE example.tabcol
( tabcol_id SERIAL NOT NULL PRIMARY KEY
, tab_id BIGINT NOT NULL REFERENCES example.zname(nam_id)
, col_id BIGINT NOT NULL REFERENCES example.zname(nam_id)
, type_id varchar NOT NULL
, CONSTRAINT tabcol_alt UNIQUE (tab_id,col_id)
);
GRANT SELECT ON TABLE example.tabcol TO PUBLIC;
DROP TABLE IF EXISTS example.entattval CASCADE;
CREATE TABLE example.entattval
( ent_id BIGINT NOT NULL
, tabcol_id BIGINT NOT NULL REFERENCES example.tabcol(tabcol_id)
, val_id BIGINT NOT NULL REFERENCES example.zvalue(val_id)
, PRIMARY KEY (ent_id, tabcol_id, val_id)
);
GRANT SELECT ON TABLE example.entattval TO PUBLIC;
BTW: this is tailored to support system catalogs; you might need a few changes.
回答4:
This is really a duplicate of this dba.SE post:
https://dba.stackexchange.com/questions/27057/model-with-variable-number-of-properties-of-different-types
Use hstore, json, xml, an EAV pattern, ... see my answer on that post.
回答5:
It is up to the admin UI you need to support:
- If there is an interface to manage for example the types of a transmission you should store this in a separate entity. (your option 3)
- If there is no such interface the best would be to store in like enumerable type values. When you need another one(for example 'semi-automatic' for the transmission) you will add this only in the DB schema, as a matter of fact this will be the easiest to support and fastest to execute
回答6:
I would create create table CarAttributes with column AttributeID,CarID,PropertyName,PropertyValue. When reslut set is returned we save it in IDictionary. It will allow you to add as many rows as you need without adding new columns.
来源:https://stackoverflow.com/questions/13425574/how-to-represent-many-similar-attributes-of-an-entity-in-a-database