Моделирование баз данных: Как правильно классифицировать такие продукты, как Amazon? - PullRequest
2 голосов
/ 27 ноября 2010

Предположим, у меня было несколько продуктов (от нескольких тысяч до сотен тысяч), которые нужно было классифицировать иерархически. Как бы я смоделировал такое решение в базе данных?

Будет ли простая таблица родитель-потомок, как эта работа:

product_category
- id
- parent_id
- category_name

Тогда в своей таблице продуктов я бы просто сделал это:

product
- id
- product_category_id
- name
- description
- price

Меня беспокоит то, что это не масштабируется. Кстати, сейчас я использую MySQL.

Ответы [ 4 ]

4 голосов
/ 27 ноября 2010

Конечно, это будет масштабироваться.Это будет хорошо работать, это часто используемая структура.

Включить level_no.Это поможет в коде, но, что более важно, необходимо исключить дубликаты.

Если вам нужна действительно узкая структура, вам нужно что-то вроде концепции Inode для Unix.

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

И, пожалуйста, измените

  • (product_category)) id на product_category_id
  • (product id до product_id
  • parent_id до parent_product_category_id

Ответы на комментарии

  1. level_no. Взгляните на эту модель данных, она предназначена для структуры дерева каталогов (например, окно обозревателя FlieManager):

    модель данных каталога

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

  2. Рекомендуемые изменения.Да, это называется Good Naming Conventions.Я не сомневаюсь в этом, и я публикую это, так что это стандарт именования.Для этого есть причины, которые станут понятны, когда вы напишете SQL с 3 или 4 уровнями объединений;особенно когда вы идете к одному и тому же родителю двумя разными способами.Если вы ищете SO, вы найдете много вопросов для этого;всегда один и тот же ответ.Это также будет выделено в следующей модели, которую я напишу для вас.

3 голосов
/ 23 сентября 2012

Я боролся с той же проблемой 10 лет назад.Вот мое личное решение этой проблемы.Но прежде чем я начну объяснять, я хотел бы упомянуть его плюсы и минусы.

Плюсы:

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

  2. То же самое можно сделать, чтобы выбрать родительские узлы.

  3. Нет конкретной СУБДособенность нужна.Таким образом, тот же метод может быть реализован в любом из них.

  4. Все это реализовано с использованием одного поля.

Минусы:

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

  2. Реструктуризация дерева обходится дороже, чем его обход.Но не так дорого, как Модель Nest Set .Добавление новой ветви - это вопрос поиска правильного значения для поля.И чтобы переместить ветку в нового родителя, вам нужно обновить этот узел и все его дочерние элементы (прямые и косвенные).Хорошая новость заключается в том, что удалить узел и его дочерние элементы так же просто, как обойти его (что абсолютно ничего).

Техника:

Рассмотрим следующую таблицу в качестве держателя дерева:

CREATE TABLE IF NOT EXISTS `product_category` (
  `product_category_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `category_code` varchar(62) NOT NULL,
  PRIMARY KEY (`product_category_id`),
  UNIQUE KEY `uni_category_code` (`category_code`)
) DEFAULT CHARSET=utf8 ;

Вся магия совершается в поле category_code.Вам необходимо закодировать адрес своей ветви в текстовое значение следующим образом:

**node_name -> category_code**
Root -> 01
First child -> 01:01
Second child -> 01:02
First grandchild -> 01:01:01
First child of second child -> 01:02:01

В приведенном выше примере каждый узел может иметь до 99 прямых дочерних элементов (при условии, что мы думаем в десятичном виде).И поскольку category_code имеет тип varchar(62), мы можем иметь глубину (62-2) / 3 = 20.Это компромисс между желаемой глубиной и количеством прямых дочерних элементов, которые может иметь каждый узел, и размером вашего поля.С научной точки зрения, это реализация полного дерева , в котором неиспользуемые ветви фактически не создаются, а зарезервированы.

Хорошие части:

Теперь представьте, что вы хотите выбрать узлы в 01:02.Вы можете сделать это, используя один запрос:

SELECT *
FROM product_category
WHERE
   category_code LIKE '01:02:%'

Выбор прямых узлов под 01:02:

SELECT *
FROM product_category
WHERE
   category_code LIKE '01:02:__'

Выбор всех предков 01:02:

SELECT *
FROM product_category
WHERE
   '01:02' LIKE CONCAT(category_code, ':%')

Плохие части:

Вставка нового узла в дерево - это вопрос поиска правильного category_code.Это можно сделать с помощью хранимой процедуры или даже на языке программирования, таком как PHP.

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

Приветствия.

0 голосов
/ 23 сентября 2012

Я думаю, что ваша большая проблема в том, что это недостаток в MySQL.Для большинства СУБД, которые поддерживают WITH и WITH RECURSIVE, вам потребуется только одно сканирование на уровень.Это делает глубокие иерархии немного проблематичными, но, как правило, не слишком плохими.

Я думаю, чтобы это работало хорошо, вам придется кодировать довольно обширную хранимую процедуру, или вам придется перейти к другой модели дерева, или выпридется перейти на другую RDBMS.Например, это легко сделать с PostgreSQL и WITH RECURSIVE, и это обеспечивает гораздо лучшую масштабируемость, чем многие другие подходы.

0 голосов
/ 27 ноября 2010

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

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

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

Что вы собираетесь делать с иерархией?

...