Способы реализации тегов - плюсы и минусы каждого - PullRequest
25 голосов
/ 22 мая 2010

Связано

Используя SO в качестве примера, какой самый разумный способ управлять тегами, если вы ожидаете, что они будут часто меняться?

Способ 1: Серьезно денормализован(с разделителями-запятыми)

table <b>posts</b>
+--------+-----------------+ 
| postId | tags            |
+--------+-----------------+
|   1    | c++,search,code |

Здесь теги разделены запятыми.

Плюсы : теги извлекаются сразу с помощью одного запроса select.Обновлять теги просто. Простое и дешевое обновление.

Минусы : дополнительный анализ при поиске тегов, трудно подсчитать, сколько сообщений используют какие теги.

(альтернативно, если ограничено чем-то вроде 5 тегов)

table <b>posts</b>
+--------+-------+-------+-------+-------+-------+
| postId | tag_1 | tag_2 | tag_3 | tag_4 | tag_5 |
+--------+-------+-------+-------+-------+-------+
|   1    | c++   |search | code  |       |       | 

Способ 2: «Слегка нормализовано» (отдельная таблица, без пересечения)

table posts
+--------+-------------------+
| postId | title             |
+--------+-------------------+
|   1    | How do u tag?     |

table taggings
+--------+---------+
| postId | tagName |
+--------+---------+
|   1    | C++     |
|   1    | search  |

Плюсы : Легкочтобы увидеть количество меток (count(*) from taggings where tagName='C++').

Минусы : tagName, вероятно, будет повторяться много, много раз.

Способ 3: классный ребенок (нормализуется с пересечениемтаблица)

table <b>posts</b>
+--------+---------------------------------------+
| postId | title                                 |
+--------+---------------------------------------+
|   1    | Why is a raven like a writing desk?   |

table <b>tags</b>
+--------+---------+
| tagId  | tagName |
+--------+---------+
|   1    | C++     |
|   2    | search  |
|   3    | foofle  |

table <b>taggings</b>
+--------+---------+
| postId | tagId   |
+--------+---------+
|   1    | 1       |
|   1    | 2       |
|   1    | 3       |

Плюсы :

  • Нет повторяющихся имен тегов.
  • Вам понравятся больше девушек.

Минусы : Менять теги дороже, чем способ № 1.

Ответы [ 5 ]

26 голосов
/ 22 мая 2010

Эти решения называются mysqlicious, scuttle и toxi.

В этой статье сравниваются преимущества и недостатки каждого.

1 голос
/ 22 мая 2010

Я бы сказал, что существует четвертое решение, которое представляет собой вариант вашего третьего решения:

Create Table Posts
(
    id ...
    , title ...
)
Create Table Tags
(
    name varchar(30) not null primary key
    , ...
)

Create Table PostTags
(
    PostId ...
    , TagName varchar(30) not null
    , Constraint FK_PostTags_Posts
        Foreign Key ( PostId )
        References Posts( Id )
    , Constraint FK_PostTags_Tags
        Foreign Key ( TagName )
        References Tags( Name )
        On Update Cascade
        On Delete Cascade
)

Обратите внимание, что я использую имя тега в качестве первичного ключа таблицы тегов. Таким образом, вы можете фильтровать определенные теги без дополнительного объединения с самой таблицей тегов. Кроме того, если вы измените имя тега, он обновит имена в таблице PostTags. Если изменение имени тега встречается редко, это не должно быть проблемой. Если изменение имени тега является обычным явлением, то я бы остановился на вашем третьем решении, где вы используете суррогатный ключ для ссылки на тег.

0 голосов
/ 09 июня 2011

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

+--------+-------+-------------------------------------+
| postId | label | value                               | 
+--------+-------+-------------------------------------+
|   1    | tag   |C++                                  |
+--------+-------+-------------------------------------+
|   1    | tag   |search                               | 
+--------+-------+-------------------------------------+
|   1    | tag   |code                                 |
+--------+-------+-------------------------------------+
|   1    | title | Why is a raven like a writing desk? |
+--------+-------+-------------------------------------+ 

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

0 голосов
/ 22 мая 2010

Я думаю, что SO использует решение № 1. Я бы пошел с # 1 или # 3.

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

0 голосов
/ 22 мая 2010

Я лично поддерживаю решение № 3.

Я не согласен с тем, что решение № 1 легче поддерживать. Подумайте о ситуации, когда вам нужно изменить имя тега.

Решение № 1:

UPDATE posts SET tag = REPLACE(tag, "oldname", "newname") WHERE tag LIKE("%oldname%")

Решение № 3:

UPDATE tags SET tag = "newname" WHERE tag = "oldname" 

Первый из них тяжелее.

Также вам приходится иметь дело с запятыми при удалении тегов (ОК, это легко сделать, но все же, сложнее, чем просто удалить одну строку в таблице taggings)

Что касается решения № 2 ... это ни рыба, ни мясо

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