2009-03-30 2 views
104

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

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

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

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

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

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

ответ

186

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

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

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

  • Concrete Table Inheritance: нет таблицы для общих атрибутов товаров. Вместо этого одна таблица для каждого типа продукта, сохраняющая как общие атрибуты продукта, так и атрибуты продукта.

  • Serialized LOB: Один стол для продуктов, сохраняющий атрибуты, общие для всех типов продуктов. В одном дополнительном столбце хранится BLOB полуструктурированных данных в формате XML, YAML, JSON или в другом формате. Этот BLOB позволяет сохранять атрибуты, специфичные для каждого типа продукта. Вы можете использовать причудливые шаблоны проектирования, чтобы описать это, например, «Фасад» и «Memento». Но независимо от того, у вас есть blob атрибутов, которые не могут быть легко запрошены в SQL; вы должны вернуть весь кадр обратно в приложение и отсортировать его там.

  • Entity-Attribute-Value: Один стол для продуктов и одна таблица, которая сводит атрибуты к строкам, а не столбцам. EAV не является корректным проектом в отношении реляционной парадигмы, но многие люди его используют. Это «Шаблон свойств», упомянутый другим ответом.См. Другие вопросы с eav tag на StackOverflow для некоторых подводных камней.

Об этом я написал об этом в презентации, Extensible Data Modeling.


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

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

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

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

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

+0

Я искал это с давних времен ... вариант 4,5 кажется хорошим ... –

+9

@ HimalayaGarg Вариант «4.5» действительно является противоположностью всей цели сообщения Билла. – user3308043

+2

В отличие от MySQL, SQL Server имеет обширную поддержку XML, XPath и XQuery. Поэтому для пользователей SQL Server лучшим вариантом будет хранение дополнительных атрибутов в столбце типа XML (вариант 4). Таким образом, вам НЕ нужно «возвращать весь кадр обратно в приложение и сортировать его там». Вы даже можете создавать индексы в столбцах XML в SQL Server. –

3

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

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

Steve Yegge называет это the Properties pattern и написал длинное сообщение об использовании этого файла.

+3

Шаблон свойств - это значение объекта-атрибута под другим именем. Он широко используется, но его хранение в реляционной базе данных нарушает правила нормализации. –

+1

Если честно, когда я прочитал описание EAV в ответе @Bills, я не совсем понял, что он объяснял. Но когда вы сказали «3 столбца: идентификатор продукта, дополнительное информационное имя, дополнительная информация», я понял концепцию. И я на самом деле сделал это раньше, и столкнулся с проблемами. Однако на данный момент я не помню, какими были эти проблемы. –

+1

@JDIsaacks В этом шаблоне распространенной проблемой является то, что мы не знаем, сколько JOINs нам нужно для извлечения всех атрибутов. – Omid

4

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

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

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

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

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

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

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

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

13

@StoneHeart

Я бы здесь с EAV и MVC весь путь.

@Bill Karvin

Вот некоторые из недостатков 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. 

для таблицы поиска.

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

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

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

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

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

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

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

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

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

+0

'вы всегда можете использовать Erlang, C++, Go Language для предварительной обработки данных. Что вы имели в виду? Вместо DB, используйте Go lang? Не могли бы вы рассказать об этом? – Green

+0

Я полностью согласен. EAV - это способ продвижения, особенно если вам нужен уровень гибкости, который позволит вам добавлять новые виды продуктов и параметров без изменений схемы дБ, я имею в виду жить в производстве через ваше приложение. Был там, сделал это. Работал для меня. О медленных запросах ... кто-нибудь из нас когда-либо слышал о кешах? ;) –

+0

@Green Я отредактировал последний абзац, чтобы сделать его более понятным, но речь идет о передаче ваших необработанных данных EAV в процесс на языке, который может обрабатывать преобразования данных, поиск в древовидной структуре или любой основной операции сокращения карты действительно быстро и эффективно в памяти. Специфика здесь будет зависеть от того, что нужно оптимизировать –

Смежные вопросы