Как разработать таблицу продуктов для многих видов продуктов, где каждый продукт имеет много параметров

У меня нет большого опыта в оформлении стола. Моя цель - создать одну или несколько таблиц продуктов, которые соответствуют требованиям ниже:

  • Поддержка многих видов продукции (телевизор, телефон, компьютер, ...). Каждый вид продукта имеет свой набор параметров, например:

    • Телефон будет иметь цвет, размер, вес, ОС...

    • ПК будет иметь процессор, жесткий диск, оперативную память...

  • Набор параметров должен быть динамическим. Вы можете добавить или отредактировать любой параметр, который вам нравится.

Как я могу удовлетворить эти требования без отдельной таблицы для каждого вида продукта?

4 ответа

Решение

У вас есть по крайней мере пять вариантов моделирования иерархии типов, которую вы описываете:

  • Наследование одной таблицы: одна таблица для всех типов Продукта, с достаточным количеством столбцов для хранения всех атрибутов всех типов. Это означает много столбцов, большинство из которых имеют значение NULL в любой строке.

  • Наследование таблиц классов: одна таблица для продуктов, хранящая атрибуты, общие для всех типов продуктов. Затем по одной таблице для каждого типа продукта, сохраняя атрибуты, специфичные для данного типа продукта.

  • Наследование бетонной таблицы: нет таблицы для общих атрибутов продуктов. Вместо этого одна таблица для каждого типа продукта, в которой хранятся как общие атрибуты продукта, так и атрибуты, специфичные для продукта.

  • Сериализированный большой объект: одна таблица для продуктов, в которой хранятся атрибуты, общие для всех типов продуктов. В одном дополнительном столбце хранится большой двоичный объект полуструктурированных данных в формате XML, YAML, JSON или в другом формате. Этот BLOB-объект позволяет хранить атрибуты, специфичные для каждого типа продукта. Вы можете использовать причудливые Шаблоны Дизайна, чтобы описать это, такие как Фасад и Мементо. Но независимо от того, у вас есть множество атрибутов, которые нельзя легко запросить в SQL; Вы должны получить весь блоб обратно в приложение и разобрать его там.

  • Entity-Attribute-Value: одна таблица для продуктов и одна таблица, которая сводит атрибуты к строкам, а не к столбцам. EAV не является допустимым проектом в отношении реляционной парадигмы, но многие люди все равно его используют. Это "Шаблон свойств", упомянутый в другом ответе. Посмотрите другие вопросы с тегом eav на Stackru для некоторых ловушек.

Я написал об этом больше в презентации " Расширяемое моделирование данных".


Дополнительные мысли о EAV: Хотя многие люди предпочитают EAV, я не согласен. Похоже, самое гибкое решение и, следовательно, лучшее. Однако имейте в виду пословицу TANSTAAFL. Вот некоторые из недостатков EAV:

  • Нет способа сделать столбец обязательным (эквивалент NOT NULL).
  • Нет способа использовать типы данных SQL для проверки записей.
  • Нет способа гарантировать, что имена атрибутов пишутся последовательно.
  • Нет способа поместить внешний ключ в значения любого заданного атрибута, например, для таблицы поиска.
  • Извлечение результатов в обычном табличном макете является сложным и дорогостоящим, потому что для получения атрибутов из нескольких строк вам нужно сделать JOIN для каждого атрибута.

Степень гибкости, которую дает вам EAV, требует жертв в других областях, вероятно, делая ваш код более сложным (или хуже), чем это было бы для решения исходной проблемы более традиционным способом.

И в большинстве случаев нет необходимости иметь такую ​​степень гибкости. В вопросе OP о типах продуктов гораздо проще создать таблицу для каждого типа продукта для атрибутов, относящихся к конкретному продукту, поэтому у вас есть некоторая согласованная структура, применяемая, по крайней мере, для записей того же типа продукта.

Я бы использовал EAV, только если каждая строка должна иметь возможность иметь отдельный набор атрибутов. Когда у вас есть конечный набор типов продуктов, EAV является излишним. Наследование таблиц классов будет моим первым выбором.

@Каменное сердце

Я бы пошел сюда с EAV и MVC до конца.

@ Билл Карвин

Вот некоторые из недостатков EAV:

No way to make a column mandatory (equivalent of NOT NULL).
No way to use SQL data types to validate entries.
No way to ensure that attribute names are spelled consistently.
No way to put a foreign key on the values of any given attribute, e.g.

для справочной таблицы.

Все те вещи, которые вы упомянули здесь:

  • проверка данных
  • проверка правописания имен атрибутов
  • обязательные столбцы / поля
  • обработка уничтожения зависимых атрибутов

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

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

Извлечение результатов в обычном табличном макете является сложным и дорогостоящим, поскольку для получения атрибутов из нескольких строк необходимо выполнить JOIN для каждого атрибута.

Эту проблему можно решить, выполнив несколько запросов к частичным данным и обработав их в виде таблицы с вашим приложением. Даже если у вас есть 600 ГБ данных о продукте, вы можете обрабатывать их партиями, если вам нужны данные из каждой строки в этой таблице.

Дальнейшие действия Если вы хотите повысить производительность запросов, вы можете выбрать определенные операции, например, для создания отчетов или глобального текстового поиска, и подготовить для них индексные таблицы, в которых будут храниться необходимые данные и которые будут периодически обновляться, скажем, каждые 30 минут.

Вам даже не нужно беспокоиться о стоимости дополнительного хранилища данных, потому что оно становится все дешевле и дешевле с каждым днем.

Если вы по-прежнему беспокоитесь о производительности операций, выполняемых приложением, вы всегда можете использовать Erlang, C++, Go Language для предварительной обработки данных, а затем просто обработать оптимизированные данные в вашем основном приложении.

Если я использую Class Table Inheritance имея в виду:

одна таблица для продуктов, хранящая атрибуты, общие для всех типов продуктов. Затем по одной таблице для каждого типа продукта, сохраняя атрибуты, специфичные для данного типа продукта. Билл Карвин

Что мне больше всего нравится в предложениях Билла Карвина. Я могу предвидеть один недостаток, который я постараюсь объяснить, как не стать проблемой.

Какой план действий в чрезвычайных ситуациях я должен иметь в наличии, когда атрибут, который является общим только для 1 типа, затем становится общим для 2, затем 3 и т. Д.?

Например: (это только пример, а не моя настоящая проблема)

Если мы продаем мебель, мы можем продавать стулья, лампы, диваны, телевизоры и т. Д. Тип телевизора может быть единственным типом, который у нас есть, с энергопотреблением. Так что я бы поставил power_consumption атрибут на tv_type_table, Но затем мы начинаем нести системы домашнего кинотеатра, которые также имеют power_consumption имущество. ОК, это просто еще один продукт, поэтому я добавлю это поле в stereo_type_table а так как это, вероятно, проще всего на данный момент. Но со временем, когда мы начинаем носить все больше и больше электроники, мы понимаем, что power_consumption достаточно широка, что должно быть в main_product_table, Что мне теперь делать?

Добавьте поле к main_product_table, Напишите скрипт для прохождения цикла по электронике и укажите правильное значение для каждого type_table к main_product_table, Затем удалите этот столбец из каждого type_table,

Если бы я всегда использовал одно и то же GetProductData класс для взаимодействия с базой данных для получения информации о продукте; затем, если какие-либо изменения в коде теперь требуют рефакторинга, они должны относиться только к этому классу.

Вы можете иметь таблицу Product и отдельную таблицу ProductAdditionInfo с 3 столбцами: идентификатор продукта, имя дополнительной информации, значение дополнительной информации. Если цвет используется многими, но не всеми видами Продуктов, это может быть пустая колонка в таблице Продуктов или просто добавление в ProductAdditionalInfo.

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

Стив Йегге назвал это шаблоном "Свойства" и написал длинный пост об его использовании.

Другие вопросы по тегам