MySQL中标签的数据库设计

时间:2016-02-09 04:17:57

标签: php mysql database

我目前正致力于在我们的网站上使用主题标签的系统,并且我在如何最好和最有效地将主题标签存储在数据库中时遇到一些麻烦。需要设置设计,以便检索与搜索词匹配的帖子相对简单(例如,当您单击主题标签的链接时,在Twitter上显示所有带有该主题标签的推文)。 通过从创建的帖子的内容中提取术语(也可以与推特相比)并插入它们,将主题标签存储在数据库中。如何插入它们当然是手头的问题: 目前,我在两种可能的设计之间徘徊:

1)我的第一个设计理念(也许更传统)是一个3桌设计:

  • 第一个表只存储帖子内容和其他相关数据 到帖子本身(我已经使用这样的表)。
  • 第二个表只存储正在使用的新主题标签,基本上用作查找已使用的所有主题标签。
  • 第三个表是一个定义主题标签和帖子之间关系的表。所以基本上是一个简单的表 将有一列具有帖子的ID和另一列 我们存储在上一个表中的单个主题标签的ID。因此,具有例如3个主题标签的帖子在该表中将具有3行,与其相关联的每个主题标签为1。

2)第二种设计是2桌设计:

  • 与上面存储的帖子数据相同的表格。
  • 第二个表是第一个设计中第2个和第3个表的混合:它保存了主题标签和 发布,但不是将新主题标签存储在分配它的表中 一个ID,它只存储实际的#标签(例如" #test") 本身以及帖子的ID。同样的概念适用于此 如果帖子中有3个主题标签,则会存储3个单独的行 桌子。

我在这些想法之间徘徊的原因是因为第一种选择确实看起来更标准,并且似乎有更多的结构"它。但是,由于它们是主题标签,因此我没有看到为每个主题标签实际分配唯一ID的目的很多,因为主题标签不是类别或类型的真正分类。

另外,当我尝试为主题标签创建搜索页面时,我必须使用较少的JOIN,因为我不需要查找搜索到的字词的ID,然后转到另一个表格并找到相关的帖子那个ID。

此外,当试图简单地列出帖子的主题标签时,一件令人讨厌的事情是,主题标签的打印方式可能与用户可能在帖子中对其进行风格化的方式不同。因此,例如,如果用户添加了#testing,但另一个用户之前已经使用#TeStIng输入了帖子,那么该帖子的主题标签将打印出#TeStIng,因为它将如何保存在数据库查找中表。当然你可以使它区分大小写,但在搜索#testing和#TeStIng应该被认为是相同的#标签,这样可能会变得混乱。或者我错了吗?有没有人建议如何避免这种情况?

另一方面,我对第二个表设计的担忧是,我担心如果表变得很大,它可能会变得低效,因为查找字符串比搜索整数要慢(我会用第一个设计做的)。但是,由于我必须在第一个设计中使用更多JOIN,实际上会有性能差异吗?为了清楚起见,当我自己搜索字符串时,我会使用=运算符而不是LIKE。

同样地,我想如果我想对主题标签本身进行查询,第一个设计效率会更高,例如有多少帖子正在使用某个标签和类似的东西,尽管它不是很难用第二个设计,我只是再次想知道效率。

关于什么可能更好的想法?最重要的是,通过hashtag搜索是有效的,所以例如我试图找到与#test相关联的帖子。理想情况下,我还希望能够从数据库中检索帖子的主题标签,因为用户在帖子内容中对其进行了样式化。此时围绕分析主题标签的所有其他查询和函数都是次要的。

1 个答案:

答案 0 :(得分:3)

纯粹从数据库规范化角度来看,您的第二个设计不会出现在3NF中。你有理由依赖整个初级而不是关键。如果哈希表中的任何内容发生更改,这会对post表产生直接影响,则会出现逻辑上的不一致。例如,主题标签表有两行:一行带有#strong> #politics 标签,另一行带有标签 #politic 。假设为第二个主题标签创建帖子的人决定编辑他们的帖子并将标签更新为 #politics 也许是因为他们输错了)。你更新了哪一行?

至于性能,我不会在第一次设计时担心它。您的数据库(就像今天几乎所有主要的关系型数据库一样)依赖于称为二叉搜索树(或更具体地说是red-black tree)的东西来优化数据库表中插入/删除/搜索的成本正确索引这些值。在某些文本搜索用例中,它可以使用O(1)(散列表查找)进一步优化此功能,或者您甚至可以在Memcached / Redis等密钥/值缓存存储中自行完成此操作。在大多数情况下,索引主题标签以便更快地搜索使用这些主题标签的帖子绝对是您想要的设计。由于最大的成本因素不是查找单个主题标签(大多数搜索都有一个我在此用例中假设的主题标签),而是检索包含该主题标签的所有帖子。

至于解决查询的不区分大小写的搜索部分,您的dbms很可能有一些您可以在模式中指定的排序规则选项(如utf8_general_ci),其中ci表示不区分大小写架构中的比较。这意味着,数据将按原样存储,但在查询中与另一个值进行比较时,MySQL会以不区分大小写的方式对字符进行比较。