如何为分区标记系统设计数据存储?

时间:2010-04-14 03:27:35

标签: database tags tagging partitioning

如何为庞大的标记系统设计数据存储(如digg或者美味)?

关于它已经有discussion,但它是关于集中式数据库的。由于数据应该增长,我们需要很快或稍后将数据分区为多个分片。那么,问题变成:如何为分区标记系统设计数据存储?

标记系统基本上有3个表:

Item (item_id, item_content)

Tag (tag_id, tag_title)

TagMapping(map_id, tag_id, item_id)

如果表存储在一个数据库实例中,那么找到给定标记的所有项目并查找给定项目的所有标记都可以。如果我们需要将数据分区为多个数据库实例,那就不那么容易了。

对于表格项目,我们可以使用其键 item_id 对其内容进行分区。对于表格标记,我们可以使用其键 tag_id 对其内容进行分区。例如,我们希望将表标记分区为K个数据库。我们可以简单地选择数字(tag_id%K)数据库来存储给定的标记。

但是,如何分区表 TagMapping

TagMapping 表表示多对多关系。我只能想象有重复。也就是说, TagMappping 的相同内容有两个副本。一个用 tag_id 分区,另一个用 item_id 分区。在查找给定项目的标记的方案中,我们使用 tag_id 的分区。如果要查找给定标记的项目,我们使用 item_id 的分区。

因此,存在数据冗余。并且,应用程序级别应该保持所有表的一致性。看起来很难。

有没有更好的解决方案来解决这个多对多分区问题?

3 个答案:

答案 0 :(得分:4)

我怀疑有一种方法可以优化所有可能的使用场景。正如您所说,TagMapping表支持两种主要方案:查找给定项的标记,以及查找具有给定标记的项。我认为对于每个可能感兴趣的场景,如何使用TagMapping表存在一些差异。我只能基于典型的标记应用程序做出合理的假设,所以请原谅我,如果这是基础的话!

查找给定项目的标记

A1。您将立即显示给定项目的所有标签

A2。您将确保项目标签的所有是唯一的

查找给定标记的项目

B1。您一次需要某些项目的某些项目(以填充搜索结果页面)

B2。您可能允许用户指定多个标记,因此您需要找到匹配多个标记的部分

B3。您将按一定程度的受欢迎程度对给定标记(或标记)的项目进行排序

鉴于上述情况,我认为一个好的方法是按项目分区TagMapping。这样,给定项的所有标记都在一个分区上。分区可以更精细,因为项目可能比标签多得多,每个项目只有少量标签。这使得检索变得容易(A1)并且可以在单个分区(A2)内实施唯一性。此外,该单个分区可以告诉您项目是否与多个标签匹配(B2)。

由于您一次只需要某个给定标记(或多个标记)的部分项目,因此您可以按某种顺序逐个查询一个分区,直到您拥有多个记录为止需要填写一页结果。您需要查询的分区数取决于您拥有的分区数,要显示的结果数以及标记的使用频率。每个分区在tag_id上都有自己的索引,可以有效地回答这个问题。

您选择分区的顺序非常重要,因为它会影响搜索结果的分组方式。如果排序不重要(即B3无关紧要),请随机选择分区,以免任何分区过热。如果排序很重要,您可以构造项目ID,以便它编码与结果排序顺序相关的信息。然后,适当的分区方案将注意到这种编码。例如,如果结果是按受欢迎程度排序的网址,则您可以将顺序商品ID与该网址(或类似内容)的Google Page Rank分数相结合。分区方案必须确保给定分区中的所有项目具有相同的分数。查询将按分数顺序选择分区,以确保首先返回更多受欢迎的项目(B3)。显然,这只允许一种排序,所涉及的属性应该是常量,因为它们现在是键的一部分并确定记录的分区。然而,这并不是一个新的限制,因为使用分区数据支持各种排序或对易失性属性进行排序并不容易。

答案 1 :(得分:1)

规则是您按要查询的字段进行分区。否则你将不得不浏览所有分区。您确定只需要通过tag_id查询Tag表吗?我不相信,你还需要按标签标题查询。对于Item表来说并不是那么明显,但是当其他用户为它分配标签时,你可能也希望通过URL之类的查询来查找item_id。

但请注意,Tag和Item表具有不可变的标题和URL。这意味着您可以使用以下技术:

  1. 从标题(用于标记)或URL(用于项目)中选择分区。
  2. 选择此分区的序列以生成ID。
  3. 您可以使用partition-localID对作为全局标识符,也可以使用非重叠数字集。无论如何,现在您可以从id和title / URL字段计算分区。事先不知道分区数量还是担心以后可能会发生变化?创建更多这些组并加入组,以便将来重新组合它们。

    当然,你不能对TagMapping表做同样的事情,所以你必须复制。你需要通过map_id,tag_id,item_id来查询,对吧?因此,即使没有分区,您也必须通过创建3个索引来复制数据。所以区别在于您为每个索引使用不同的分区(通过不同的字段)。我认为没有理由担心。

答案 2 :(得分:1)

您的查询很可能与用户主题相关。这意味着您应该在一个地方拥有与这些信息相关的所有信息。

您在谈论数据库的分发,通常这主要是同步的问题。阅读,通常是大约90%的工作,可以在复制的数据库上完成。问题是如何更新一个数据库,并保持所有其他数据库的一致性,而不会破坏性能。这取决于您的方案详细信息。

另一种可能性就是像你问的那样对所有数据进行分区而不重叠。您可能会按用户ID或主题ID进行分区。如果按主题ID进行分区,则一个数据库可以引用所有主题,只是告诉哪个专用DB保存数据。然后,您可以查询正确的。由于您按ID进行分区,因此与该主题相关的所有信息都可以在该专用数据库上。您也可以通过语言国家/地区对国际网站进行分区。

最后但并非最不重要的是,您可能最终会混淆两者:一些非重叠数据和一些重叠(复制)数据。首先找到常规操作,然后找到如何在一个DB上进行最少可能的查询。

PS:不要忘记缓存,它比分布式数据库更省钱。