0

我正在构建一个多站点平台,类似于 StackExchange,它有多个社区使用相同的平台并共享数据。

用户可以像标记堆栈交换问题一样“标记”他们的内容。创建标签概念的最佳架构是什么?

我想到的一些小笔记是别名(同义词)的概念。此外,我一方面认为我希望跨站点共享标签(这样人们就可以看到来自另一个站点的同一主题的内容),但另一方面,不同社区的上下文可能不同。例如,计算机中的“图形”是一种数据结构,而数学则是别的东西(只是我脑海中的一个随机例子——不确定它是否重要)。

另外,如果我有一个英语社区和一个法语社区...

你怎么看?

4

2 回答 2

1

要以完全标准化的方式执行此操作,您需要以下内容:

在此处输入图像描述

MEANING_ITEM 具有以下索引:

  • {SITE_ID, MEANING_NO, ITEM_NO} - 自动为主键创建,并且可以有效地搜索具有给定标签的项目。
  • {ITEM_NO, SITE_ID, MEANING_NO} - 可以有效地查询相反的内容:“获取给定项目的标签”。

注意:如果您的 DBMS 支持它,请考虑将此表聚类。聚簇表中的二级索引可能很昂贵(因为它们需要包含整个 PK 的副本并且可能导致双重查找),但在这种情况下,两个索引都包含相同的字段(因此所有“额外”字段都已经在二级index) 并且索引之外没有字段,因此不需要双重查找。通过集群,您只是消除了(无用的)表堆,并且只剩下两个 B 树。

该模型具有以下属性:

  • 标签和项目都以特定于站点的方式标识,默认情况下查询特定于站点的标签。如果您想查询标签名称而不考虑站点,只需SITE_ID = ...从下面查询中的 WHERE 子句中省略即可。由于 TAG_NAME 处于 TAG PK 的前沿,因此无需额外索引即可有效满足无站点查询。
  • 项目不能使用来自“错误”站点的标签进行标记。我们正在使用识别关系,它将 SITE_ID 传播到“菱形”依赖关系的两个边缘,合并到“菱形”的底部(在 MEANING_ITEM 中),这就是为我们提供这种保证的原因。
  • 标签同义词被有效地表示(在同一站点内具有相同含义的标签被视为同义词)。如果我们尝试在标签上实现 M:N 自关系,则不会发生各种异常。1
  • 由于标签的含义是特定于站点的,因此同义词也是特定于站点的。
  • MEANING 表是存储有关标签的附加信息(例如描述)的自然位置,这些信息将由所有同义词共享。

1我们如何处理同义词及物性?如果 A、B 和 C 是同义词,我们是只存储 AB 和 BC 还是同时存储 AC?我们如何执行它?如果我们不强制执行它,我们将需要某种递归查询来选择所有依赖项。每个连接都需要一行,浪费空间和性能。

要获取具有任何给定标签的项目,您需要执行类似于此的查询...

SELECT *
FROM ITEM
WHERE EXISTS (
    SELECT *
    FROM TAG JOIN MEANING_ITEM ON
        TAG.SITE_ID = MEANING_ITEM.SITE_ID
        AND TAG.MEANING_NO = MEANING_ITEM.MEANING_NO
    WHERE
        TAG.SITE_ID = <site id>
        AND TAG.NAME IN ( <list of tags> )
        AND ITEM.SITE_ID = MEANING_ITEM.SITE_ID
        AND ITEM.ITEM_NO = MEANING_ITEM.ITEM_NO
)

注意:我们可以从上面的查询中完全省略 JOIN 到 MEANING - JOIN 所需的所有字段都已经在 TAG 中。

对于具有所有给定标签的项目,您需要一些 COUNTing,类似于以下内容:

SELECT *
FROM ITEM
WHERE <number of tags> = (
    SELECT COUNT(DISTINCT TAG_NAME)
    FROM TAG JOIN MEANING_ITEM ON
        TAG.SITE_ID = MEANING_ITEM.SITE_ID
        AND TAG.MEANING_NO = MEANING_ITEM.MEANING_NO
    WHERE
        TAG.SITE_ID = <site id>
        AND TAG.NAME IN ( <list of tags> )
        AND ITEM.SITE_ID = MEANING_ITEM.SITE_ID
        AND ITEM.ITEM_NO = MEANING_ITEM.ITEM_NO
)

现在这看起来像很多 JOIN-ing,但这个模型非常适合集群(又名索引组织)表和使用索引覆盖查询。

在考虑出于性能原因对这种设计进行非规范化之前,您可能需要接近 StackExchange 的真实数据量(例如,通过删除联结表并限制每个项目的标签数量)。

在任何情况下,在进行任何特定设计之前,都要测量实际的数据量。

于 2012-07-12T15:53:22.063 回答
0

我会建议这样的模型:

ERD

您保留一个可用标签列表,这些标签适用于您使用标准多对多交集表标记的任何项目。

要管理标签的同义词,请在可用标签表上使用内卷关系。这假设在作为同义词的各种标签中,一个被认为是“主要”标签。

可用的标签有一个语言标志来指示英语或法语。如果您为加拿大政府或其他机构执行此操作,并且需要确保所有内容都以两种语言显示,您可以添加一个内卷的一对一(未显示)AVAILABLE_TAG以链接等效的英语和法语标签。

要跨站点共享标签,请使用另一个与表格的多对多交集SITE来显示哪些标签属于哪个站点。如果这些标签在每个站点上的含义不同,我会避免跨站点共享标签。

于 2012-07-12T11:49:39.870 回答