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


    场景

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

    在这里插入图片描述

    实现方式有很多,我们来聊比较常用的两种,看看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='当前信息'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

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

    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='内容表'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

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

    对比

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

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

    总结

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

  • 相关阅读:
    【泛函分析】距离空间的完备性
    Redis基础篇:初识Redis(认识NoSQL,单机安装Redis,配置Redis自启动,Redis客户端的基本使用)
    Flink - Kafka 下发消息过大异常分析与 Kafka Producer 源码浅析
    【FFmpeg】学会添加水印,只要这一篇就足够
    洛谷刷题笔记 确定进制
    重生之我是一名程序员 38
    阿里巴巴资深架构师深度解析微服务架构设计之SpringCloud+Dubbo
    第三方模块远程注入到软件中引发软件异常的若干实战案例分享
    ERD Online 4.0.4 元数据在线建模(免费、私有部署)
    【工具】一键生成动态歌词字幕
  • 原文地址:https://blog.csdn.net/shida219/article/details/133517108