MySQL案例分享之系统消息

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

    从前有个大师,率领一群徒弟,为客户做了一个软件系统。某天,客户提出了一个新的需求,向系统中的所有用户发送系统消息。由于当时系统刚上线不久,系统中的用户也就几十个。大师为了考验自己的徒弟,便将该需求分配给他的徒弟,要求每个人都做一套方案出来,于是便有了下面的故事。


    徒弟们接收到该项任务后,每个人都想到了先建一张系统消息表,每次发送系统消息时,将数据保存在词表中,用户就能从该表中读取他个人的系统消息。用户信息表的模型如下:

wKiom1SE7u-CszJkAAEpCtm5nzk125.jpg


    基于上面的数据库模型,徒弟们分别作了不同的实现方案,如下:


    实现方案一:


    小A是个急性子,领到任务后。立即开始了他的编程思路:将系统中的所有用户都取出来,然后遍历所有的用户,每次迭代时插入一条系统消息。伪代码如下:


1
2
3
4
5
6
7
List<FavUser> userList = favUserService.getAllUser();
for (FavUser favUser : userList){
     SysMessage sysMessage =  new  SysMessage();
     ...
     sysMessage.setReceiveUserId(favUser.getUserId());
     sysMessageService.addSysMessage(sysMessage);
}


    由于系统中的用户较少,小A几遍测试,发现系统中运行良好,便将该方案提交了上去。


    实现方案二:


    小B接到任务后,想到应该先把系统中所有的用户Ids取出来,然后遍历这些ids,每次迭代时都插入一条系统消息。基于此,小B的伪代码如下:

1
2
3
4
5
6
7
List<Integer> userIdsList = favUserService.getAllUserIds();
for (Integer userId : userIdsList ){
     SysMessage sysMessage =  new  SysMessage();
     ...
     sysMessage.setReceiveUserId(userId);
     sysMessageService.addSysMessage(sysMessage);
}


    由于系统中的用户较少,小B几遍测试,发现系统中运行良好,也将该方案提交了上去。


    实现方案三:


    小C接到任务后,考虑到每次插入的系统消息,除了用户id不同外,其余的数据项都相同,便想到了批量插入数据。由于MySQL数据库支持批量插入数据,小C设计出了执行的SQL语句与伪代码:


    执行的SQL语句如下:


1
2
3
4
5
6
7
8
9
< insert  id= "addBatchSysMessage"  parameterType= "com.favccxx.favsoft.SysMessage"  >
      insert  into  sys_message (MESSAGE_TITLE,  MESSAGE_CONTENT, MESSAGE_STATUS, RECEIVE_USER_ID,  RECEIVE_TIME, CREATE_TIME 
        )
      values
      <foreach collection= "list"  item= "item"  index = "index"  separator= "," >
            ( #{item.messageTitle,jdbcType= VARCHAR },#{item.messageContent,jdbcType= VARCHAR }, #{item.messageStatus,jdbcType= CHAR }, #{item.receiveUserId,jdbcType= INTEGER },#{item.receiveTime,jdbcType= TIMESTAMP },  #{item.createTime,jdbcType= TIMESTAMP }
        )
       </foreach>
   </ insert >


  伪代码如下:


1
2
3
4
5
6
7
8
List<FavUser> userList = favUserService.getAllUser();
List<SysMessage> dataList =  new  ArrayList<SysMessage>();
for (FavUser favUser : userList){
     sysMessage.setReceiveUserId(favUser.getUserId());
     dataList.add(sysMessage);
}
List<SysMessage> subList = dataList.subList( 0 , 1000 );
sysMessageService.addBatchSysMessage(subList);


    小C向系统中添加了几千个模拟用户,测试系统运行良好。但发现将系统中的用户增加至几万时,发送系统消息速度明显变慢。于是,小C采用了分组的方式进行插入,每10,000条插入一次,系统运行良好。

    实现方案四


    小D接到任务后,考虑的也是批量插入数据,但与小C不同的是,他想通过执行一次SQL完成批量插入数据。即先将待发送的消息存入数据库中,然后通过MySQL查询并同时将数据插入系统消息。小D的MySQL设计如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< insert  id= "addAllSysMessage"  parameterType= "com.favccxx.favsoft.SysMessage"  >
     insert  into  sys_message ( MESSAGE_TITLE,
            MESSAGE_CONTENT, MESSAGE_STATUS, RECEIVE_USER_ID,
            RECEIVE_TIME, CREATE_USER_ID, CREATE_TIME
     )
     select
         a.MESSAGE_TITLE  as  MESSAGE_TITLE,
         a.MESSAGE_CONTENT  as  MESSAGE_CONTENT,
         as  MESSAGE_STATUS,
         b.user_id  AS  RECEIVE_USER_ID,
         now()  as  RECEIVE_TIME,
          now()  as  CREATE_TIME
     from  sys_message_send_info a,
     (
          select  user_id  FROM  auth_user
     ) b
     where  sendInfoId=#{sendInfoId}
  </ insert >
1
int  insertCount = sysMessageService.addAllSysMessage(sendInfoId);


  小D向系统中插入了10万个模拟用户,经测试,系统运行良好。以下是向113508个用户发送消息的花费时间。


“可爱 的测试发送给系统中【113508】个用户,共用时【2241】毫秒  

fdgsdfg发送给分组中【113508】个用户,共用时【2236】毫秒  

平台所有用户系统消息发送给系统中【113508】个用户,共用时【1916】毫秒   

发生的飞洒的发送给系统中【113508】个用户,共用时【1217】毫秒 

测试用户组33发送给分组中【113508】个用户,共用时【1617】毫秒


    上面的故事,便是我们在开发中经常遇到的场景,要实现系统中的一个功能时,往往有很多种方法,最先实现的,代码最简便的并不一定是效率最好的。代码本身就是一个黑盒子,不要考虑程序的现有性能,更要考虑好程序的扩展性能。





本文转自 genuinecx 51CTO博客,原文链接:http://blog.51cto.com/favccxx/1587394,如需转载请自行联系原作者
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
19天前
|
安全 关系型数据库 MySQL
如何将数据从MySQL同步到其他系统
【10月更文挑战第17天】如何将数据从MySQL同步到其他系统
112 0
|
1月前
|
分布式计算 关系型数据库 MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
48 3
|
1月前
|
SQL 关系型数据库 MySQL
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
|
1月前
|
SQL 关系型数据库 MySQL
案例剖析,MySQL共享锁引发的死锁问题!
案例剖析,MySQL共享锁引发的死锁问题!
|
1月前
|
消息中间件 关系型数据库 MySQL
大数据-117 - Flink DataStream Sink 案例:写出到MySQL、写出到Kafka
大数据-117 - Flink DataStream Sink 案例:写出到MySQL、写出到Kafka
123 0
|
11天前
|
关系型数据库 MySQL Linux
Linux系统如何设置自启动服务在MySQL数据库启动后执行?
【10月更文挑战第25天】Linux系统如何设置自启动服务在MySQL数据库启动后执行?
59 3
|
15天前
|
关系型数据库 MySQL 数据库
一个 MySQL 数据库死锁的案例和解决方案
本文介绍了一个 MySQL 数据库死锁的案例和解决方案。
19 3
|
18天前
|
存储 关系型数据库 MySQL
基于案例分析 MySQL 权限认证中的具体优先原则
【10月更文挑战第26天】本文通过具体案例分析了MySQL权限认证中的优先原则,包括全局权限、数据库级别权限和表级别权限的设置与优先级。全局权限优先于数据库级别权限,后者又优先于表级别权限。在权限冲突时,更严格的权限将被优先执行,确保数据库的安全性与资源合理分配。
|
25天前
|
存储 关系型数据库 MySQL
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
21 2
|
25天前
|
Ubuntu 关系型数据库 MySQL
Linux系统MySQL安装
【10月更文挑战第19天】本文介绍了在 Linux 系统上安装 MySQL 的步骤,包括安装前准备、安装 MySQL、启动 MySQL 服务、配置 MySQL 以及验证安装。适用于 Ubuntu/Debian 和 CentOS/Fedora 系统,提供了详细的命令示例。
131 1
下一篇
无影云桌面