Ответ 1
Эти решения называются mysqlicious
, scuttle
и toxi
.
В этой статье сравниваются преимущества и недостатки каждого из них.
Используя SO в качестве примера, что является наиболее разумным способом управления тегами, если вы ожидаете, что они будут часто меняться?
table posts +--------+-----------------+ | postId | tags | +--------+-----------------+ | 1 | c++,search,code |
Здесь теги разделены запятой.
Плюсы. Теги извлекаются сразу с помощью одного запроса select
. Обновление тегов прост. Легко и дешево обновить.
Минусы: дополнительный синтаксический анализ при поиске тегов, трудно подсчитать, сколько сообщений использует теги.
(альтернативно, если ограничено чем-то вроде 5 тегов)
table posts +--------+-------+-------+-------+-------+-------+ | postId | tag_1 | tag_2 | tag_3 | tag_4 | tag_5 | +--------+-------+-------+-------+-------+-------+ | 1 | c++ |search | code | | |
table posts +--------+-------------------+ | postId | title | +--------+-------------------+ | 1 | How do u tag? | table taggings +--------+---------+ | postId | tagName | +--------+---------+ | 1 | C++ | | 1 | search |
Плюсы. Легко видеть количество тегов (count(*) from taggings where tagName='C++'
).
Минусы: tagName будет повторяться много раз.
table posts +--------+---------------------------------------+ | postId | title | +--------+---------------------------------------+ | 1 | Why is a raven like a writing desk? | table tags +--------+---------+ | tagId | tagName | +--------+---------+ | 1 | C++ | | 2 | search | | 3 | foofle | table taggings +--------+---------+ | postId | tagId | +--------+---------+ | 1 | 1 | | 1 | 2 | | 1 | 3 |
Профи:
Минусы: дороже менять теги, чем путь №1.
Эти решения называются mysqlicious
, scuttle
и toxi
.
В этой статье сравниваются преимущества и недостатки каждого из них.
Я бы сказал, что есть четвертое решение, которое является вариацией вашего третьего решения:
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. Если изменение имени тега является редким явлением, это не должно быть проблемой. Если изменение имени тега является обычным явлением, я бы пошел с вашим третьим решением, где вы используете суррогатный ключ для ссылки на тег.
Я лично одобряю решение №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... не является ни рыбой, ни птицей
Я думаю, что SO использует решение # 1. Я бы пошел С# 1 или # 3.
Можно подумать, есть ли у вас несколько вещей, которые вы можете пометить (например, добавив теги как к сообщениям, так и к продуктам, например). Это может повлиять на решение базы данных.
Ну, у меня такое же сомнение, что я принял третье решение для своего сайта. Я знаю, что есть другой способ справиться с этой проблемой кортежей переменной длины, который состоит в использовании столбцов в виде строк таким образом, что у вас будет определенная информация, идентифицирующая фидуданта кортежа и различные, которые будут организованы по одному для каждой строки.
+--------+-------+-------------------------------------+
| postId | label | value |
+--------+-------+-------------------------------------+
| 1 | tag |C++ |
+--------+-------+-------------------------------------+
| 1 | tag |search |
+--------+-------+-------------------------------------+
| 1 | tag |code |
+--------+-------+-------------------------------------+
| 1 | title | Why is a raven like a writing desk? |
+--------+-------+-------------------------------------+
Это действительно плохо, но иногда это единственное возможное решение, и оно очень далекое от реляционного подхода.