【问题标题】:Ways to implement tags - pros and cons of each实现标签的方法 - 每种方法的优缺点
【发布时间】:2011-02-22 13:19:44
【问题描述】:

Related

以 SO 为例,如果您预计标签会经常更改,那么管理标签最明智的方法是什么?

方式1:严重非规范化(逗号分隔)

帖子 +--------+-----------------+ |邮编 |标签 | +--------+-----------------+ | 1 | c++,搜索,代码 |

这里的标签是逗号分隔的。

优点:使用单个 select 查询即可立即检索标签。更新标签很简单。 更新简单且便宜。

缺点:标签检索需要额外解析,很难统计有多少帖子使用了哪些标签。

(或者,如果限制为 5 个标签)

帖子 +--------+-------+-------+-------+-------+-------+ |邮编 |标签_1 |标签_2 |标签_3 |标签_4 |标签_5 | +--------+-------+-------+-------+-------+-------+ | 1 | c++ |搜索 |代码 | | |

方式2:“稍微规范化”(单独的表,没有交集)

桌柱 +--------+-------------------+ |邮编 |标题 | +--------+-------------------+ | 1 |你如何标记? | 表标签 +--------+---------+ |邮编 |标记名 | +--------+---------+ | 1 | C++ | | 1 |搜索 |

优点:易于查看标签计数 (count(*) from taggings where tagName='C++')。

缺点:tagName 可能会重复很多很多次。

方式 3:酷孩子的(用交集表标准化)

帖子 +--------+---------------------------------------------------+ |邮编 |标题 | +--------+---------------------------------------------------+ | 1 |为什么乌鸦像写字台? | 表标签 +--------+---------+ |标签标识 |标记名 | +--------+---------+ | 1 | C++ | | 2 |搜索 | | 3 |傻瓜| 表标记 +--------+---------+ |邮编 |标签标识 | +--------+---------+ | 1 | 1 | | 1 | 2 | | 1 | 3 |

优点

  • 没有重复的标签名称。
  • 会有更多女孩喜欢你。

缺点:更改标签的成本比方法 1 高。

【问题讨论】:

  • 我会向在您之前必须管理标签的人发送电子邮件/推特。喜欢 Jeff Atwood 或其他 SO 开发人员之一。他们或许能够提供一些见解。
  • 听起来你刚刚回答了这个问题。因此,只需选择最符合您要求的那个。如果您希望女孩喜欢您,请选择#3。
  • 更多女孩会喜欢你的,嗯?我喜欢这个选择!
  • 我不是 sql 专家。您能否告诉我是否应该在taggings 表中添加一个包含postIdtagId 的主键?这样可以防止多次将相同的标签添加到帖子中。

标签: sql tags


【解决方案1】:

这些解决方案称为mysqliciousscuttletoxi

This article 比较各自的优缺点。

【讨论】:

【解决方案2】:

我认为有第四个解决方案是您的第三个解决方案的变体:

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 表中的名称。如果更改标签名称很少发生,那么这应该不是问题。如果更改标签名称很常见,那么我将采用您的第三个解决方案,您可以使用代理键来引用标签。

【讨论】:

  • @Thomas:这与scuttle 相同,只是更难管理。写UPDATE Tags SET TagName = 'newtag' WHERE TagName = 'oldtag' 而不是UPDATE PostTags SET TagName = 'newtag' WHERE TagName = 'oldtag' 的可能性并不值得。
  • @Quassnoi - 使用 Cascade Update,您只需编写 Update Tags Set Name = 'NewName' Where Name = 'OldName'。如果您使用代理键,则不会更难管理。真正的问题是避免额外连接的好处是否超过了您更改现有标签名称的频率。由于我认为后者并不常见,因此性能优势可能是值得的。
  • @Thomas:再说一遍,它与方式 2 (scuttle) 有何不同,只是多了一张无用的桌子 (Tags)?
  • @Quassnoi - 该设计更接近于 Toxi 而不是 scuttle。标签表有一个非常重要的用途。它确保您无法在 PostTags 中添加标签表中尚未拥有的标签引用。即,您仍然维护一个标签列表。此外,它允许您在标签上添加其他属性,就像使用 Toxi 设置一样。不同之处在于,如果您想要一个给定标签的帖子列表,您可以避免 have 加入标签表的额外工作(当然,您仍然可以)。数以千计的行没有任何区别,但数百万行会有所不同。
  • @Quassnoi - 请记住,在 Toxi 设置的标签表中,您仍然需要对标签名称的唯一约束,并且它可能是不可为空的。在这种情况下,您不妨将其用作主键除非您知道您将有 许多 调用来更改我认为不太可能的标签名称。
【解决方案3】:

我个人赞成解决方案 #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... 非鱼非禽

【讨论】:

    【解决方案4】:

    我认为 SO 使用解决方案 #1。我会选择 #1 或 #3。

    要考虑的一件事是,如果您有几个可以标记的东西(例如,为帖子和产品添加标签)。这可能会影响数据库解决方案。

    【讨论】:

      【解决方案5】:

      嗯,我有同样的疑问,我为我的网站采用了第三种解决方案。我知道还有另一种处理可变长度元组问题的方法,即使用列作为行,这样您将获得一些信息来识别元组冗余和为每一行组织一个不同的元组。

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

      这确实很糟糕,但有时它是唯一可行的解​​决方案,而且与关系方法相去甚远。

      【讨论】:

      • 然而它很容易更新和维护,查询速度变慢但是你可能会遇到同时加入来自 3 个不同表的大量元组的问题,你可以考虑使用不同的索引来增加某些类型的查询的性能。希望这会有所帮助
      猜你喜欢
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-13
      • 1970-01-01
      • 2010-10-29
      • 2014-01-03
      • 1970-01-01
      相关资源
      最近更新 更多