在数据库中存储标签的最有效方法是啥?
Posted
技术标签:
【中文标题】在数据库中存储标签的最有效方法是啥?【英文标题】:What is the most efficient way to store tags in a database?在数据库中存储标签的最有效方法是什么? 【发布时间】:2010-09-24 22:52:21 【问题描述】:我正在我的网站上实现一个类似于 *** 使用的标记系统,我的问题是 - 存储标记以便可以搜索和过滤它们的最有效方法是什么?
我的想法是这样的:
Table: Items
Columns: Item_ID, Title, Content
Table: Tags
Columns: Title, Item_ID
这太慢了吗?有没有更好的办法?
【问题讨论】:
上一个问题:***.com/questions/20856/… 自 2016 年起,使用 Solr 或 Elasticsearch 【参考方案1】:一个项目将有许多标签。一个标签将属于许多项目。这对我来说意味着您很可能需要一个中间表来克服多对多的障碍。
类似:
表格:项目 列:Item_ID、Item_Title、内容
表格:标签 列:Tag_ID、Tag_Title
表:Items_Tags 列:Item_ID、Tag_ID
这可能是因为您的网络应用程序非常受欢迎,并且需要在未来进行去规范化,但过早地搅浑水是没有意义的。
【讨论】:
相关:***.com/questions/20856/… 如果有诸如 tagGroup 之类的东西如何处理它,例如标签被分组到类别中,例如:编程语言:c#、vb、pearl。操作系统:windows7、dos、linux等 @Thunder:假设一个标签可能只属于一个类别,我将创建一个包含 category_id 和 category_name 的 TagCategory 表。从那里,我会将 category_id 字段附加到 Tags 表并对其执行连接。【参考方案2】:实际上,我相信对标签表进行去规范化可能是更好的方法,具体取决于规模。
这样,tags 表就只有 tagid、itemid、tagname。
你会得到重复的标签名,但它使添加/删除/编辑特定项目的标签更加简单。您不必创建新标签,删除旧标签的分配并重新分配新标签,您只需编辑标签名。
要显示标签列表,您只需使用 DISTINCT 或 GROUP BY,当然您也可以轻松计算标签的使用次数。
【讨论】:
【参考方案3】:如果您不介意使用一些非标准的东西,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
对性能进行彻底比较的各种选项更多,上面建议的选项总体上是最好的。
【讨论】:
【参考方案4】:根据您在问题中提供的数据,您无法真正谈论缓慢。而且我认为您甚至不应该在这个开发阶段过分担心性能。它叫做premature optimization。
但是,我建议您在标签表中包含 Tag_ID 列。每个表都有一个 ID 列通常是一个好习惯。
【讨论】:
【参考方案5】:我建议使用中间的第三张表来存储标签项目关联,因为我们在标签和项目之间有多对多的关系,即一个项目可以与多个标签相关联,一个标签可以与多个项目。 高温下, 阀门。
【讨论】:
【参考方案6】:如果空间将成为问题,请使用第三个表 Tags(Tag_Id, Title) 来存储标签的文本,然后将 Tags 表更改为 (Tag_Id, Item_Id)。这两个值也应该提供唯一的复合主键。
【讨论】:
【参考方案7】:项目应该有一个“ID”字段,标签应该有一个“ID”字段(主键,集群)。
然后制作一个 ItemID/TagID 的中间表,并将“Perfect Index”放在那里。
【讨论】:
【参考方案8】:标记架构:标记表和属性:
表格:
tags (each row only keeps information about a particular tag)
taggings (each row keeps information about trigger and who will receive the trigger )
products_tags (each row keeps information about tag with particular product)
tag_status (each row keeps track of a tag status)
表格:tags 表格的属性:
id(PK)
userId(FK users)(not null)(A tag only belongs to one user, but a user can create multiple tags. So it is one to many relationships.)
genreId(FK products_geners)(not null)
name (string) (not null)
description (string)
status (int) (0=inactive, 1=pending, 2=active, there could be more flag)
rank(int) (rank is the popularity of a particular tag), this field can be use for sorting among similar tags.)
type (int) (0=type1, 1=type2, 2=type3)
photo(string)
visibility (int) (0=public, 2=protected, 3 = private)(private means the tag only visible to assigned users of a product, protected means a tag only visible to all friends and followers of the creator of the tag, public means search by public, such as all admin created tag)
createdAt(timestamp for the tag was created at)
updatedAt (timestamp for the tag last time updated)
deletedAt (default value null) (timestamp when tag was deleted, we need this field because we will delete tag permanently from audit table).
注意:保留第 10 号字段稍后会派上用场。
表格:标签:
此表将用于触发,例如广播其他用户的提要或向他们发送通知。在此表中插入一行后,将有一个读取行的服务执行相关操作以删除该行。
标签表的属性:
Id(PK)
tagId(a tagging row only belongs to a tag, but a tag can have multiple row).
taggableId (id of a user who will receive notification)
taggableType(int) (0=notification, 1=feed message)
taggerId(the person who triggered the broadcast)
taggerType(ad, product, news)
createdAt(timestamp for the tag was created at)
表格:products_tags
从用户的角度来看,用户可以在实例化产品后创建标签,因此下表将保留有关哪些产品具有哪些标签的信息。
taggings table的Attributes的属性:
Id (PK)
productId(FK)
tagId(FK)
表:tag_status
当用户创建标签时,将在此表中创建一个带有 tagId 和默认状态为 inactive/pending 的行,管理员将从标签表中提取所有标签,其中 status=pending/inactive,如果管理员批准了标签,则在查看标签后标记然后标记表中的状态值将被批准,并且标记状态行将被删除。如果 admin 被拒绝,则 tag_status 表的 status 字段的值将被拒绝,并且将广播触发器,并且接收器将向该标签的关联用户发送通知,其中包含他的标签被拒绝的消息。
id(PK)
senderId(Id of the user)
receiverId(Id of admin user)
createdAt(timestamp of created at)
updatedAt(timestamp of updated at)
deletedAt(timestamp of deletedAt) default value null
expiredAt (if a tag never gets approved it will expire after a certain time for removing its information from the database. If a rejected tag gets updated by user then expiredAt will reset to new future time)
status
Message (string varchar(256)) (message for user)
【讨论】:
以上是关于在数据库中存储标签的最有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 Marklogic 数据库中存储名称/值对的最有效方法是啥
在数据库中的一组记录上存储排序顺序的最有效方法是啥? [关闭]
(预)处理存储在 json 中的大型数据集的最有效方法是啥?