Как представить много похожих атрибутов объекта в базе данных?

Предположим, я строю сайт об автомобилях. Автомобильный объект имеет множество атрибутов переименования:

  • трансмиссия (ручная / автоматическая)
  • топливо (бензин / дизель / биоэтанол / электрический)
  • body style (купе / седан / кабриолет / …)
  • кондиционер (нет / простой / двухзонный)
  • цвет кузова (черный / белый / серый / синий / зеленый / …)
  • цвет интерьера (черный / белый / серый / синий / зеленый / …)
  • и т.п.

Список этих атрибутов, скорее всего, изменится в будущем. Каков оптимальный способ их моделирования в базе данных? Я могу думать о следующих вариантах, но не могу решить:

  • использовать поля в таблице car с значениями перечисления
    • трудно добавить больше столбцов позже, возможно, самый быстрый
  • использовать поля в таблице car которые являются внешними ключами, ссылающимися на таблицу поиска
    • трудно добавить больше колонок позже, несколько медленнее
  • создавать отдельные таблицы для каждого из этих атрибутов, которые хранят возможные значения, и другую таблицу для хранения соединения между автомобилем и значением атрибута
    • легко добавить более возможные значения позже, еще медленнее, кажется слишком сложным

    В зависимости от количества запросов и размера баз данных вы можете:

    1. Сделать широкие столы
    2. Создайте таблицу аттрибутов и таблицу car_attributes, где: cars -> car_attributes -> attributes

    # 1 будет делать более быстрые и простые запросы из-за меньшего количества соединений, но # 2 более гибкий

    Идеализм заключается в создании реляционной базы данных. Каждая таблица из БД должна быть представлена ​​классом, как в спящем режиме. Вы должны сделать 2 стола для машины. Один для интерьера и один для внешнего вида автомобиля. Если вы хотите добавить дополнительные функции, вы просто добавляете больше столбцов.

    Теперь вот (очень простая) модель EAV:

     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: это адаптировано для поддержки системных каталогов; вам может потребоваться несколько изменений.

    Это действительно дубликат этой записи dba.SE:

    https://dba.stackexchange.com/questions/27057/model-with-variable-number-of-properties-of-different-types

    Используйте hstore, json, xml, образец EAV, … см. Мой ответ на этот пост.

    Это зависит от пользовательского интерфейса администратора, который вам необходимо поддерживать:

    • Если есть интерфейс для управления, например, типами передачи, вы должны хранить это в отдельном объекте. (ваш вариант 3)
    • Если такого интерфейса нет, лучше всего хранить в виде перечислимых значений типа. Когда вам понадобится другой (например, «полуавтоматический» для передачи), вы добавите это только в схему БД, на самом деле это будет проще всего поддерживать и быстрее выполнять

    Я бы создал create CarAttributes таблицы с столбцом AttributeID, CarID, PropertyName, PropertyValue. Когда возвращается reslut set, мы сохраняем его в IDictionary. Это позволит вам добавить столько строк, сколько нужно, без добавления новых столбцов.