Как создать таблицу продуктов для многих видов продуктов, где каждый продукт имеет много параметров
У меня нет большого опыта в дизайне таблиц. Моя цель-создать одну или несколько таблиц продуктов, которые отвечают требованиям ниже:
поддержка многих видов продукции (ТВ, телефон, ПК, ...). Каждый вид продукта имеет различный набор параметров, таких как:
телефон будет иметь цвет, размер, вес, ОС...
ПК будет иметь процессор, жесткий диск, оперативную память...
набор параметры должны быть динамическими. Вы можете добавить или изменить любой параметр, который вам нравится.
Как я могу выполнить эти требования без отдельной таблицы для каждого вида продукта?
4 ответов:
у вас есть по крайней мере эти пять вариантов моделирования иерархии типов, которую вы описываете:
Наследование Одной Таблицы: одна таблица для всех типов товара, с достаточным количеством столбцов для хранения всех атрибутов всех типов. Это значит большое столбцов, большинство из которых имеют значение NULL в любой заданной строке.
Наследование Таблицы Классов: одна таблица для продуктов, хранящая атрибуты, общие для всех типов продуктов. Затем одна таблица для каждого типа продукта, хранящая атрибуты, характерные для этого типа продукта.
Наследование Конкретной Таблицы: нет таблицы для общих атрибутов продуктов. Вместо этого используется одна таблица для каждого типа продукта, в которой хранятся как общие атрибуты продукта, так и атрибуты конкретного продукта.
сериализованный LOB: одна таблица для продуктов, хранящая атрибуты, общие для всех типов продуктов. Один дополнительный столбец хранит большой двоичный объект полуструктурированные данные, в XML, YAML, JSON или каком-либо другом формате. Этот большой двоичный объект позволяет хранить атрибуты, характерные для каждого типа продукта. Вы можете использовать причудливые шаблоны дизайна, чтобы описать это, такие как фасад и сувенир. Но независимо от того, у вас есть blob атрибутов, которые не могут быть легко запрошены в SQL; вы должны вернуть весь blob обратно в приложение и отсортировать его там.
Объект-Атрибут-Значение: одна таблица для продуктов, и одно таблица, которая сводит атрибуты к строкам, а не столбцам. EAV не является допустимым дизайном в отношении реляционной парадигмы, но многие люди используют его в любом случае. Это "шаблон свойств", упомянутый в другом ответе. См. другие вопросы с eav tag на StackOverflow для некоторых подводных камней.
Я уже писал об этом в презентации, Расширяемое Моделирование Данных.
дополнительные мысли о EAV: хотя многие люди, похоже, предпочитают EAV, я этого не делаю. это кажется самым гибким решением и, следовательно, лучшим. Однако, имейте в виду пословицу TANSTAAFL. Вот некоторые из недостатков EAV:
- нет способа сделать столбец обязательным (эквивалент
NOT NULL).- невозможно использовать типы данных SQL для проверки записей.
- невозможно гарантировать, что имена атрибутов пишутся последовательно.
- нет возможности поставить внешний ключ для значений любого заданного атрибута, например для таблицы подстановки.
- получение результатов в обычной табличной компоновке является сложным и дорогостоящим, потому что для получения атрибутов из нескольких строк вам нужно сделать
JOINдля каждого атрибута.степень гибкости EAV дает вам требует жертв в других областях, вероятно, делая ваш код как сложный (или хуже), чем это было бы, чтобы решить исходную проблему в более обычной путь.
и в большинстве случаев нет необходимости иметь такую степень гибкости. В вопросе OP о типах продуктов гораздо проще создать таблицу для каждого типа продукта для атрибутов, специфичных для продукта, поэтому у вас есть некоторая согласованная структура, применяемая, по крайней мере, для записей одного и того же типа продукта.
Я бы использовал подслушивание только если строка должно быть разрешено потенциально иметь отдельный набор атрибутов. Когда у вас есть конечный набор типов продуктов, Подслушивать-это перебор. Наследование таблицы классов было бы моим первым выбором.
@StoneHeart
Я бы пошел сюда с EAV и MVC всю дорогу.
@Bill Karvin
вот некоторые из недостатков Подслушивание:
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 и т. д.?
например: (это просто пример, а не моя реальная проблема)
если мы продаем мебель, мы продаем стулья, светильники, диваны, телевизоры и т. д. Тип телевизора может быть единственным типом, который мы носим, который имеет энергопотребление. Так что я бы поставил на
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 столбцами: идентификатор продукта, дополнительное имя информации, дополнительное значение информации. Если цвет используется многими, но не всеми видами продуктов, вы можете иметь столбец с нулевым значением в таблице Product или просто поместить его в ProductAdditionalInfo.
этот подход не является традиционным методом для реляционной базы данных, но я видел, как это используется в практике. Он может быть гибким и иметь хорошую производительность.
Стив Yegge называет это свойства pattern и написал длинный пост о ее использовании.
Comments