Mor*_*eng 8 database tags tagging partitioning
如何设计大型标签系统的数据存储(如digg或美味)?
已经讨论过它,但它是关于集中式数据库的.由于数据应该增长,我们需要很快或稍后将数据分区为多个分片.因此,问题变成:如何为分区标记系统设计数据存储?
标记系统基本上有3个表:
Item (item_id, item_content)
Tag (tag_id, tag_title)
TagMapping(map_id, tag_id, item_id)
Run Code Online (Sandbox Code Playgroud)
如果表存储在一个数据库实例中,那么找到给定标记的所有项并找到给定项的所有标记都可以.如果我们需要将数据分区为多个数据库实例,那就不那么容易了.
对于表项,我们可以使用其键item_id对其内容进行分区.对于表Tag,我们可以使用其key_id对其内容进行分区.例如,我们希望将表Tag分区为K个数据库.我们可以简单地选择数字(tag_id%K)数据库来存储给定的标签.
但是,如何分区表TagMapping?
该TagMapping表代表了许多一对多的关系.我只能想象有重复.也就是说,TagMappping的相同内容有两个副本.一个用tag_id分区,另一个用item_id分区.在为给定项找到标签的场景中,我们使用带有tag_id的分区.如果要查找给定标记的项目,我们使用带有item_id的分区.
结果,存在数据冗余.并且,应用程序级别应该保持所有表的一致性.看起来很难.
有没有更好的解决方案来解决这个多对多的分区问题?
我怀疑是否有一种方法可以优化所有可能的使用场景。正如您所说,该TagMapping表支持两种主要场景:查找给定项目的标签,以及查找具有给定标签的项目。TagMapping我认为对于您可能感兴趣的每个场景,如何使用该表存在一些差异。我只能根据典型的标记应用程序做出合理的假设,所以如果这是错误的,请原谅我!
查找给定项目的标签
A1。您将立即显示给定项目的所有标签
A2。您将确保所有项目的标签都是唯一的
查找给定标签的项目
B1。您将一次需要给定标签的一些项目(以填充搜索结果页面)
B2. 您可能允许用户指定多个标签,因此您需要查找一些与多个标签匹配的项目
B3。您将按照某种受欢迎程度对给定标签(或多个标签)的项目进行排序
鉴于上述情况,我认为一个好的方法是按TagMapping项目进行分区。这样,给定项目的所有标签都位于一个分区上。分区可以更细粒度,因为项目的数量可能远多于标签,并且每个项目只有少数标签。这使得检索变得容易 (A1),并且可以在单个分区内强制执行唯一性 (A2)。此外,该单个分区可以告诉您某个项目是否与多个标签匹配 (B2)。
由于您一次只需要给定标签(或多个标签)的某些项目 (B1),因此您可以按某种顺序一次查询一个分区,直到拥有填充一页结果所需的记录。您需要查询的分区数量取决于您拥有的分区数量、您想要显示的结果数量以及标签的使用频率。每个分区在 tag_id 上都有自己的索引,以有效地回答此查询。
您选择分区的顺序非常重要,因为它将影响搜索结果的分组方式。如果顺序不重要(即 B3 不重要),请随机选择分区,以免任何分区变得太热。如果排序很重要,您可以构造项目 id,以便它对与结果排序顺序相关的信息进行编码。适当的分区方案将注意这种编码。例如,如果结果是按受欢迎程度排序的 URL,则您可以将顺序项目 ID 与该 URL 的 Google Page Rank 分数(或任何类似内容)结合起来。分区方案必须确保给定分区内的所有项目具有相同的分数。查询将按分数顺序选择分区,以确保首先返回更受欢迎的项目 (B3)。显然,这仅允许一种排序,并且涉及的属性应该是恒定的,因为它们现在是键的一部分并确定记录的分区。但这并不是一个真正的新限制,因为无论如何使用分区数据支持各种排序或易失性属性的排序并不容易。