Database design 标签体系结构

Database design 标签体系结构,database-design,architecture,Database Design,Architecture,我正在构建一个多站点平台,类似于StackExchange,它有多个社区使用同一平台并共享数据 用户可以像标记堆栈交换问题一样“标记”其内容。创建标记概念的最佳架构是什么 我想到的一些小注释是别名(同义词)的概念。我还认为,一方面,我希望标签能够在各个站点之间共享(这样人们就可以看到其他站点关于同一主题的内容),但另一方面,不同社区的上下文可能不同。例如,计算机中的“图形”是一种数据结构,而数学是另一种东西(只是我脑海中的一个随机例子——不确定它是否重要) 如果我有一个英语社区和一个法语社区 你

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

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

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

如果我有一个英语社区和一个法语社区


你觉得怎么样?

我建议这样的模式:

保留可用标记的列表,这些标记将应用于使用标准多对多交叉表标记的任何项目

要管理标记的同义词,请在“可用标记”表上使用渐开线关系。这假设在同义词的各种标记中,有一个被认为是“主”标记

可用标记有一个语言标志,表示英语或法语。如果您是为加拿大政府或其他机构这样做的,并且需要确保所有内容都以两种语言显示,您可以在
AVAILABLE_TAG
上添加一个内卷一对一(未显示)来链接等效的英语和法语标记


要跨站点共享标记,请使用另一个多对多交叉点和
站点
表来显示哪些标记属于哪个站点。如果标签在每个站点上的含义不同,我会避免在各个站点之间共享标签。

要以完全规范化的方式进行共享,您需要以下内容:

含义_项具有以下索引:

  • {SITE_ID,意思是_NO,ITEM_NO}-自动为主键装箱,并启用对具有给定标记的项的有效搜索
  • {ITEM_NO,SITE_ID,意思是{u NO}-能够高效地查询相反的内容:“获取给定项的标记”
注:如果DBMS支持它,请考虑此表。聚集表中的二级索引可能很昂贵(因为它们需要包含整个PK的副本,并且可能导致双重查找),但在这种情况下,两个索引都包含相同的字段(因此所有“额外”字段都已在二级索引中),并且索引之外没有字段,因此,没有必要进行双重查找。通过集群,您只需消除(无用的)表堆,只剩下两个B树

此模型具有以下属性:

  • 标记和项目都是以特定于站点的方式标识的,默认情况下,您可以查询特定于站点的标记。如果您想查询标记名而不考虑站点,只需在下面的查询中的WHERE子句中省略
    site\u ID=…
    。由于TAG_NAME位于TAG PK的前沿,因此无需额外的索引就可以高效地满足无站点查询
  • 不能使用来自“错误”站点的标签标记项目。我们正在使用标识关系,它将站点ID传播到“菱形”依赖项的两个边缘,并合并到“菱形”(意思是“项目”)的底部,这就是我们的保证
  • 有效地表示标记同义词(在同一站点中具有相同含义的标记被视为同义词)。如果我们试图在标记上实现M:N自我关系,就没有可能发生各种异常的空间。1
  • 由于标记的含义是特定于站点的,因此同义词也是特定于站点的
  • 语义表是存储有关标记的附加信息(如描述)的自然位置,所有同义词都将共享这些信息
1我们如何处理同义词及物性?如果A、B和C是同义词,我们是只存储A-B和B-C还是同时存储A-C?我们如何执行它?如果我们不强制执行它,我们将需要某种递归查询来选择所有依赖项。每个连接都需要一行,这会浪费空间和性能

要获取包含给定标记的任何
项,您需要执行类似于以下内容的查询

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
)
选择*
从项目
哪里有(
挑选*
来自标记连接,表示\u项目位于
TAG.SITE\u ID=表示\u ITEM.SITE\u ID
和TAG.meansion\u NO=meansion\u ITEM.meansing\u NO
哪里
TAG.SITE_ID=
以及()中的TAG.NAME
和ITEM.SITE\u ID=表示\u ITEM.SITE\u ID
和ITEM.ITEM\u NO=表示\u ITEM.ITEM\u NO
)
注意:我们可以从上面的查询中完全省略JOIN to的含义-JOIN所需的所有字段都已经在标记中了

对于具有所有给定标记的项目,您需要进行一些计数,如下所示:

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
)
选择*
从项目
其中=(
选择计数(不同的标记名称)
来自标记连接,表示\u项目位于
TAG.SITE\u ID=表示\u ITEM.SITE\u ID
和TAG.meansion\u NO=meansion\u ITEM.meansing\u NO
哪里
TAG.SITE_ID=
以及()中的TAG.NAME
和ITEM.SITE\u ID=表示\u ITEM.SITE\u ID
和ITEM.ITEM\u NO=表示\u ITEM.ITEM\u NO
)
现在,这看起来像是大量的连接,但是这个模型对于集群(aka.)表和带有索引的查询来说是非常好的

出于性能原因,在考虑对该设计进行非规范化之前,您可能需要接近实际StackExchange的数据量(例如,删除连接表并限制每个项的标记数)


在任何情况下,在提交任何特定设计之前,请测量实际数据量。

如何管理标记?在大多数站点(如StackOverflow),用户可以快速轻松地创建标签。标签是否与正式类别相同,即在编辑过程中严格管理,或者它们是