Возможно, вы захотите посмотреть на «расстояние» меры - см. Ответы на этот вопрос Редактировать сходство расстояний в Lucene / Solr
Эти решения называются 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? |
+--------+-------+-------------------------------------+
Это действительно плохо, но иногда это единственно возможное решение, и оно очень далеко от реляционного подхода.