Database design 标签体系结构
我正在构建一个多站点平台,类似于StackExchange,它有多个社区使用同一平台并共享数据 用户可以像标记堆栈交换问题一样“标记”其内容。创建标记概念的最佳架构是什么 我想到的一些小注释是别名(同义词)的概念。我还认为,一方面,我希望标签能够在各个站点之间共享(这样人们就可以看到其他站点关于同一主题的内容),但另一方面,不同社区的上下文可能不同。例如,计算机中的“图形”是一种数据结构,而数学是另一种东西(只是我脑海中的一个随机例子——不确定它是否重要) 如果我有一个英语社区和一个法语社区Database design 标签体系结构,database-design,architecture,Database Design,Architecture,我正在构建一个多站点平台,类似于StackExchange,它有多个社区使用同一平台并共享数据 用户可以像标记堆栈交换问题一样“标记”其内容。创建标记概念的最佳架构是什么 我想到的一些小注释是别名(同义词)的概念。我还认为,一方面,我希望标签能够在各个站点之间共享(这样人们就可以看到其他站点关于同一主题的内容),但另一方面,不同社区的上下文可能不同。例如,计算机中的“图形”是一种数据结构,而数学是另一种东西(只是我脑海中的一个随机例子——不确定它是否重要) 如果我有一个英语社区和一个法语社区 你
你觉得怎么样?我建议这样的模式: 保留可用标记的列表,这些标记将应用于使用标准多对多交叉表标记的任何项目 要管理标记的同义词,请在“可用标记”表上使用渐开线关系。这假设在同义词的各种标记中,有一个被认为是“主”标记 可用标记有一个语言标志,表示英语或法语。如果您是为加拿大政府或其他机构这样做的,并且需要确保所有内容都以两种语言显示,您可以在
AVAILABLE_TAG
上添加一个内卷一对一(未显示)来链接等效的英语和法语标记
要跨站点共享标记,请使用另一个多对多交叉点和
站点
表来显示哪些标记属于哪个站点。如果标签在每个站点上的含义不同,我会避免在各个站点之间共享标签。要以完全规范化的方式进行共享,您需要以下内容:
含义_项具有以下索引:
- {SITE_ID,意思是_NO,ITEM_NO}-自动为主键装箱,并启用对具有给定标记的项的有效搜索
- {ITEM_NO,SITE_ID,意思是{u NO}-能够高效地查询相反的内容:“获取给定项的标记”
- 标记和项目都是以特定于站点的方式标识的,默认情况下,您可以查询特定于站点的标记。如果您想查询标记名而不考虑站点,只需在下面的查询中的WHERE子句中省略
。由于TAG_NAME位于TAG PK的前沿,因此无需额外的索引就可以高效地满足无站点查询site\u ID=…
- 不能使用来自“错误”站点的标签标记项目。我们正在使用标识关系,它将站点ID传播到“菱形”依赖项的两个边缘,并合并到“菱形”(意思是“项目”)的底部,这就是我们的保证
- 有效地表示标记同义词(在同一站点中具有相同含义的标记被视为同义词)。如果我们试图在标记上实现M:N自我关系,就没有可能发生各种异常的空间。1
- 由于标记的含义是特定于站点的,因此同义词也是特定于站点的
- 语义表是存储有关标记的附加信息(如描述)的自然位置,所有同义词都将共享这些信息
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),用户可以快速轻松地创建标签。标签是否与正式类别相同,即在编辑过程中严格管理,或者它们是