在数据库中存储标签。标签应该只存储一次还是多次存储?

8

我希望能更清楚地了解在stackoverflow上提到的使用toxi方法将标签存储在数据库中的方式。

数据库模式如下:

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID

这可能是一个愚蠢的问题(但我不知道答案)...<table>标记中的每个条目是否都应该具有唯一的标题。即,我只存储一次标记还是每次使用时都存储它?

为了举例说明,下面的两个表格中哪个应该是最终结果:

TagID     Title
1         Fish
2         Cat
3         Dog

或者

TagID     Title
1         Fish
2         Fish
3         Cat
4         Fish
5         Dog
6         Cat

如果使用第一个表格,在输入标签之前,我需要先运行SQL语句来确定它是否存在,对吗?
任何帮助都将不胜感激。最近由于拼凑和索引而导致我的手指被烧伤,我想开始正确地掌握基础知识。

在您的第二个解决方案中,您实际上并不需要标签表,只需将标签保存在ItemTag表中而不是TagID中。不过我会选择第一个解决方案。 - Vertigo
3个回答

4
基本原则是您需要像第一种情况所示那样存储标签。这对于检查标签是否存在很有用(因为在第二种情况下,对于现有标签,您的数据库将返回与该标签出现次数相同的行数),并且对于通过标签检索项目也很有用(通过一个标签 ID 选择项目 ID 要比通过具有相同表示意义的 tag_id 集合选择项目 ID 更好)。
如果您因索引而受到伤害-您应始终检查查询的执行方式(对于 MySQL,它是 EXPLAIN/DESCRIBE SELECT)。

2
如果“Fish”和“Fish”是相同的标签,您应该在Tag表中只拥有它一次。因此,我建议您采用第一种解决方案——确实需要在插入之前进行选择,以确定标记是否已经存在;如果存在,则在ItemTag表中使用其已经存在的TagID来链接项目和标记。实际上,这就是ItemTag存在的原因:它是一个关联表,用于存储项目和标记之间的对应关系:对于每个项目,您可以有多个标记,对于每个标记,您也可以有多个项目。顺便说一下,这也将使得获取附加到特定标记的项目列表更容易。

1
在标签表中,标签应该只出现一次;ItemTag表的整个目的是为您提供一个n:m的关联(每个项目有多个标签,每个标签属于多个项目)。
如果您重复使用标签标题,您可以通过使标签表直接使用ItemIDs而不是标签IDs来简化结构。

-1:重复标签,并让标签表使用item_ids将使搜索变得非常消耗资源,因为搜索将通过比较字符串而不是整数进行,这会慢得多。 - Eimantas
@Eimantas:我并没有建议重复标签。我只是认为,如果要重复标签,你可以删除一个表格。 - Martin v. Löwis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接