【问题标题】:How to design a relational database for associating multiple tags with id?如何设计一个将多个标签与id关联的关系数据库?
【发布时间】:2018-06-01 13:08:38
【问题描述】:

我正在开发一个Q/A网站的项目,这个网站的一个问题可以链接多个标签。

例如:How can I implement quicksort in C++ ?

这个问题的标签可以是C, C++, Algorithm

我的问题是如何将这些标签存储在 MySQL 表中?

我的做法:

上面的问题有id = 123

-------------------------
|question_id | tags     |
-------------------------
| 123        |  C       |
-------------------------
| 123        |  C++     |
-------------------------
| 123        |Algorithm |
-------------------------
| 124        | Java     |
-------------------------

但是如果我在这个意义上创建一个表格,那么对于很多问题,表格会变得非常大。

有没有更好更有效的方式来存储这类数据?

【问题讨论】:

    标签: mysql database-design relational-database


    【解决方案1】:

    有一个恰好包含 3 列的额外表格:被标记的项目的 id、标签、订购信息。

    当您添加或删除一个项目时,从该表中添加或删除所有相关行。

    详情在这里:http://mysql.rjweb.org/doc.php/lists
    高效、快速、简单且高度可扩展。

    【讨论】:

      【解决方案2】:

      为了让你的标签保持简洁,让标签本身成为一流的实体,而不仅仅是一些随机的字符串列:

      CREATE TABLE tags (
        id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
        label VARCHAR(255) NOT NULL,
        UNIQUE KEY `index_on_label` (label)
      );
      

      然后在问题和标签之间有一个小而简单的连接表:

      CREATE TABLE question_tags (
        question_id INT NOT NULL,
        tag_id INT NOT NULL,
        UNIQUE KEY `index_on_question_tag` (question_id, tag_id),
        KEY `index_on_tag` (tag_id)
      );
      

      这应该包括查询一个问题有什么标签和一个标签有什么问题。

      【讨论】:

      • 如何提高速度?我认为连接会使查询变慢。我不赞成使用联接,您能否进一步澄清答案?或提出替代方案。
      • 纯 int 表的索引大小会更小,而且question_tags 表的存储大小会通过固定长度的行最小化。所有这些都是积极的好处。将字符串放入其中是一个很好的第一步,但如果这不是缩放,我会尝试这个下一步。想想数据库必须做多少工作来比较“算法”。它必须应用排序规则,处理潜在的多字节字符,等等。这会变得非常混乱。
      【解决方案3】:

      管理信息系统中的标签有两种方法。我们在简单性和低性能复杂性和困难性和高性能之间权衡

      第一个解决方案:使用 TAG Table 以及 Our_Table 和 TAG 表之间的多对多关系。 (正如@tadman 描述的那样)

      第二种解决方案: 如果我们想要一种非常快速和高性能的方式来检索与特定标签相关的数据,我们可以使用Bit-Mask Solution

      标签管理系统的位掩码解决方案(之前针对类似问题描述过here

      在这种方法中我们有相同的表(正如@tadman 所说)。 只需将 1 个字段,longbigint(与我们的 DBMS 相关)添加到想要有 TAG(如 Question)的表中

      此字段以二进制格式显示Question 的标签。例如假设我们在 TAG 表中有 8 条记录。
      1- 一些 TAG 1
      2- 一些 TAG 2
      ...
      8- 一些 TAG 8

      那么如果我们想将标签 1,3,6,7 设置为一个Question,只需使用这个数字 01100101。
      (我提供使用二进制 (0,1) 放置的反转版本来支持额外的未来的 TAG。)

      我们可以使用10基数添加到数据库中(101而不是01100101)

      然后,要为任何给定的标签找到合适的Questions,只需从Question 中选择并使用bitwise AND,如下所示。


      A:(显示我们在 Question 中查看的 TAG 序列,如 5 为 00000101)
      B:(显示任何 Question 的 TAG,例如 101 为 01100101)

      select * from Question q
      where A & q.B  = q.B
      

      此查询返回具有特定 TAG 子集的所有问题。

      我们可以使用 Bit-Wise 操作的其他功能,例如 A & q.B > 0,在 AB 之间返回至少 1 个相等的 TAG。等等。

      注意:
      1:当添加或删除新标签时,我们遇到了一些额外的困难。但这是一个权衡。添加或删除新标签的情况较少。
      2:我们也应该使用QuestionTagsQuestion_Tags 表。但在搜索中,我们只是使用新字段。

      【讨论】:

      • 位掩码:SET 的限制为 64。8.0 版之前的按位运算限制:64。
      猜你喜欢
      • 2014-11-30
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      相关资源
      最近更新 更多