5

Mysql以key-val存储、正常存储的区别

 7 months ago
source link: https://shidawuhen.github.io/2023/10/03/Mysql%E4%BB%A5key-val%E5%AD%98%E5%82%A8%E3%80%81%E6%AD%A3%E5%B8%B8%E5%AD%98%E5%82%A8%E7%9A%84%E5%8C%BA%E5%88%AB/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Mysql以key-val存储、正常存储的区别

2023-10-03

你作为一个服务端工程师,假设产品要求设计这么一个页面,页面上包含很多模块,每个模块都可以单独进行变更,有些模块是富文本。

image-20231002120754023

实现方式有很多,我们来聊比较常用的两种,看看mysql的表如何设计。

第一种使用key-val的方案,这就需要两张表。

CREATE TABLE `playground` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '名称',
`operator_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '操作人id',
`status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '状态,1使用 2删除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_operator_id` (`operator_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB COLLATE=utf8mb4_general_ci COMMENT='playground项目信息'


CREATE TABLE `current_info` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`playground_id` bigint unsigned NOT NULL COMMENT 'playground_id',
`item_type` int NOT NULL DEFAULT '0' COMMENT '每个模块的id',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '模块内容',
`operator_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '操作人id',
`status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '状态,1使用 2删除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_playground_id` (`playground_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='当前信息'

第二种方式则是放在一张表记录

CREATE TABLE `current_info` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '名称',
`description` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '描述',
`status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '状态,0无效,1有效',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`creator_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '创建者ID',
`a` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'a模块内容',
`b` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'b模块内容',
PRIMARY KEY (`id`),
KEY `idx_creator_id` (`creator_id`),
KEY `idx_create_time` (`create_time`),
KEY `idx_update_time` (`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='内容表'

对于这两种方案,你会如何选择?

我个人建议选择正常存储的方案,因为适应面更加广泛

Key-val 正常存储
优点 增加新模块,服务端无需感知,前端自行增加即可 实现复杂度低很多
缺点 1. 即使是普通的列表,实现起来也比较复杂,必须有一张主表
2.列表排序、筛选不好实现,如按照修改时间排序、根据名称筛选等
3.数量多,页面数据会有多条
4.字段浪费严重,每个字段必须一样,大部分情况是是text
每次有新增模块,服务端需要一起修改。但这个比较正常,大部分时候新增的功能,服务端总是需要做一些改动的

对于技术方案的选择,十分重要,尤其是作为第一版的设计者。怎么知道哪个方案更加合适呢?我的想法是找到当前的各个场景和预判将来的各个场景,思考一下如果用某套方案实现这些场景,成本如何。

扫一扫,分享到微信

微信分享二维码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK