使用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更贵。
答案 0 :(得分:25)
这些解决方案称为mysqlicious
,scuttle
和toxi
。
This article比较了每种方法的优点和缺点。
答案 1 :(得分:1)
我认为第四种解决方案是第三种解决方案的变体:
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
)
请注意,我使用标记名称作为Tags表的主键。通过这种方式,您可以过滤某些标签,而无需额外连接到Tags表本身。此外,如果更改标记名称,它将更新PostTags表中的名称。如果更改标签名称很少发生,那么这应该不是问题。如果更改标签名称是常见的情况,那么我将使用您的第三个解决方案,您可以使用代理键来引用标签。
答案 2 :(得分:0)
我个人赞成解决方案#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 ......既不是鱼也不是鸡?
答案 3 :(得分:0)
我认为SO使用解决方案#1。我会选择#1或#3。
要考虑的一件事是,如果您有几件可以标记的东西(例如,为帖子和产品添加标签)。这可能会影响数据库解决方案。
答案 4 :(得分:0)
我有同样的疑问,我为我的网站采用了第三种解决方案。我知道还有另一种处理变长元组问题的方法,其中包括使用列作为行,这样你就可以获得一些信息来识别元组减少量,而变量元素则为每行组织一个。
+--------+-------+-------------------------------------+
| postId | label | value |
+--------+-------+-------------------------------------+
| 1 | tag |C++ |
+--------+-------+-------------------------------------+
| 1 | tag |search |
+--------+-------+-------------------------------------+
| 1 | tag |code |
+--------+-------+-------------------------------------+
| 1 | title | Why is a raven like a writing desk? |
+--------+-------+-------------------------------------+
这真的很糟糕,但有时它是唯一可行的解决方案,而且距离关系方法还很远。