前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >标签系统的数据存储方案设计思考与梳理

标签系统的数据存储方案设计思考与梳理

作者头像
明月AI
发布2023-08-26 15:01:12
1.7K0
发布2023-08-26 15:01:12
举报
文章被收录于专栏:野生AI架构师

最近参与的中小学生健康档案系统,涉及到很多标签数据的存储,这里做一个梳理和整理。

说明:下面所说的存储都是指在MySQL上的存储,暂时不考虑mongodb、ES这些,毕竟引入新的数据库,会让系统更加复杂。

标签相关需求

基于标签的功能通常有几种:

  1. 查询某些标签关联的item有哪些;
  2. 统计标签的分布情况,例如统计某个范围内item对应标签的分布情况;
  3. item关联标签的增删。

标签通常还有两类比较不同的形态:

  1. 单一标签,例如视力标签,要么只能是正常/近视/远视三者中的一种;
  2. 多标签,例如文章的标签,一篇文章通常可以有多个标签。

这两类标签的存储和应用应该是很大不同的,对于单一标签的存储是比较简单的,通常是直接设置为字段。

多标签存储设计

基于对MySQL固有认知,标签系统设计方案通常有几种:

第一种:使用关联表对标签进行关联,这是常见的比较保险的设计

代码语言:javascript
复制
item表:
id, title, ...
tag表:
id, name, ...
item_tag表:
item_id, tag_id, ...

好处:支持任意多的标签;

坏处:对分析类需求不是太友好,例如进行关联分析等。

第二种:大宽表,就是把所有标签直接设置为字段:

代码语言:javascript
复制
item表:
id, title, tag_1, tag_2, ...

好处:只有一个表,查询可以非常高效,特别是在分析时优势明显;

坏处:不能支持太多的标签数量,增加标签的时候,可能需要更改表结构。

第三种:直接把标签拼成字符串进行存储:

代码语言:javascript
复制
item表:
id, title, tags...
tag表:
id, name, ...

tags字段可以将众多的标签id用逗号分隔进行存储,这里也可以不用tag表,直接把tag值存储到item表中。

好处:比较简单,不需要维护关联表;

坏处:对查询和统计非常不友好,索引基本无效(也不是完全无效,使用全文索引应该是有效果的);另外,这个对增删也很不友好。

第四种:直接使用二进制标志位:

代码语言:javascript
复制
item表:
id, title, bin_tags...

bin_tags定义为二进制标签字段,每个二进制位表示某个标签是否存在,通常最多只能适用于标签数量固定,且小于64(长整型)的情况(可以使用bin类型突破这个限制,不过这个类型比较少用,不知道兼容性怎么样)。

好处:相对于第三种,非常节省空间,位运算也比直接使用like进行匹配高效很多;

坏处:使用场景非常受限,标签数量稍微多点或者标签可能变化比较大的时候,就很不适合,另外索引通常也是无效的。

基于JSON类型的多标签存储方案

MySQL支持json数据已经有一段时间了,只是一直还没使用过,关于json类型的使用,看这篇文章,这里不过多介绍。简单说,就是MySQL其实直接直接存储json数据,而且还能对其进行索引,这正好可以解决标签存储及查询问题,这时表结构应该类似这样:

代码语言:javascript
复制
item表:
id, title, tags...
tag表:
id, name, ...

这时tags字段应该存储的是json数据,格式如:[1,2,5] 表示这个item关联的标签有id为1,2和5的三个标签,这里不直接使用标签名而是使用id,主要是为了解决提升索引的效率。

不需要维护关联表,使用简单,可读性也好,而且还能支持索引,表面上看是比较完美解决了这个问题。

不过这个设计在大数据量下性能怎么样,有待验证,网上的文章很少有涉及大数据量下的性能数据,可能兼容性还不够好,使用的人还比较少。(相对而言,可能PG数据库对json的支持会比较完善些,不过我们使用的是MySQL)

多种单一标签的存储设计

在我们系统里,有一个应用场景是这样的:每个学生会有多个类别的健康相关的标签,例如视力/营养等,每个类别下是单标签,例如视力只能是正常/近视/远视三者之一。

这种单一标签正常考虑肯定是直接放到数据表的字段上,这样查询/统计都很方便(例如统计视力的分布情况),对分析师也很友好。不过这里设计的困惑在于:

  1. 标签的类别很多,造成表的字段很多,这可能会对MySQL造成压力,不过对列式存储的数仓应该不成问题;
  2. 这些标签的类别没法保证将来不会变化,放到字段里可能会加大后续的维护工作量。

如果使用关联表:

而如果把标签独立成表,通过关联表进行关联,这样确实以后的扩展性确实可能会好些,不过查询性能和统计性能可能就会比较差一些,而这个正是这个项目重点要解决的问题。

如果使用json:

这可能是一个比较好的方案,开始也是这么想的,但是在我们的这个场景暂时却不是很适用,因为我们这些数据会被实时同步到数仓中,而合作的数仓暂时还不支持json结构。对于不需要同步到数仓的一些业务逻辑表,使用json应该是比较合适的,只要保证MySQL的版本比较高就行。

所以,在这个场景下,采用大宽表独立成字段可能暂时是目前比较合适的方案。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 野生AI架构师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档