在数据库中存储标签的最有效方法是什么?


138

我正在网站上实施类似于一个stackoverflow使用的标记系统,我的问题是-存储标记以便对其进行搜索和过滤的最有效方法是什么?

我的想法是这样的:

Table: Items
Columns: Item_ID, Title, Content

Table: Tags
Columns: Title, Item_ID

这太慢了吗?有没有更好的办法?



1
截至2016年,使用Solr或Elasticsearch
Charles L.

Answers:


189

一个项目将具有许多标签。一个标签将属于许多项目。对我而言,这意味着您很可能需要一个中介表来克服多对多障碍。

就像是:

表格:项目
列:Item_ID,Item_Title,内容

表:标签
列:Tag_ID,Tag_Title

表格:Items_Tags
列:Item_ID,Tag_ID

可能是您的Web应用程序疯狂流行,并且需要在未来进行非正规化处理,但为时过早地弄糊涂毫无意义。



如果有诸如tagGroup之类的东西,如何处理它,例如,将标签分为以下类别:编程语言:c#,vb,pearl。操作系统:Windows7,DOS,Linux等
Thunder

4
@Thunder:假设一个标签只能属于一个类别,那么我将创建一个由category_id和category_name组成的TagCategory表。从那里,我将category_id字段附加到“标签”表,并在该表上执行连接。
Simon Scarfe

113

您应该阅读Philipp Keller的有关标记数据库模式的博客文章。他尝试了一些并报告了结果,无论是从构造常见查询的难易程度还是在性能方面。标签数,标签项目数和每个项目的标签数都是因素。这些职位是2005年的;从那时起,我不知道有任何更新。


19
我认为这是最好的答案。它基于实际的测试和研究,而不是像大多数其他答案一样的假设。
Cristian Vrabie 2010年


8

实际上,我相信对标签表进行非规范化可能是一种更好的方法,具体取决于规模。

这样,标签表仅具有tagid,itemid,tagname。

您将获得重复的标记名,但是它使为特定项目添加/删除/编辑标记更为简单。您无需创建新标记,只需删除标记名即可删除旧标记的分配并重新分配新标记。

要显示标签列表,您只需使用DISTINCT或GROUP BY,当然,您也可以计算轻松使用标签的次数。


4

如果您不介意使用一些非标准的东西,则Postgres 9.4及更高版本可以选择存储JSON文本类型的记录。

您的架构为:

Table: Items
Columns: Item_ID:int, Title:text, Content:text

Table: Tags
Columns: Item_ID:int, Tag_Title:text[]

有关更多信息,请参见Josh Berkus的出色文章:http ://www.databasesoup.com/2015/01/tag-all-things.html

全面比较了性能方面的更多选项,以上建议的选项是总体上最好的。


2

我建议使用中间的第三张表来存储标签<=>项目关联,因为我们在标签和项目之间具有多对多的关系,即一个项目可以与多个标签关联,而一个标签可以与多个项目关联。HTH,阀门。


1

您不能真正根据问题中提供的数据来谈论慢度。而且我认为您在此发展阶段不必担心性能。这称为过早优化

但是,建议您在“标签”表中添加“ Tag_ID”列。每个表都有一个ID列通常是一个好习惯。


1

如果空间不足,请使用第3个表标签(Tag_Id,标题)存储标签文本,然后将“标签”表更改为(Tag_Id,Item_Id)。这两个值也应提供唯一的复合主键。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.