场景
你作为一个服务端工程师,假设产品要求设计这么一个页面,页面上包含很多模块,每个模块都可以单独进行变更,有些模块是富文本。
实现方式有很多,我们来聊比较常用的两种,看看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 | 每次有新增模块,服务端需要一起修改。但这个比较正常,大部分时候新增的功能,服务端总是需要做一些改动的 |
总结
对于技术方案的选择,十分重要,尤其是作为第一版的设计者。怎么知道哪个方案更加合适呢?我的想法是找到当前的各个场景和预判将来的各个场景,思考一下如果用某套方案实现这些场景,成本如何。