MySQL案例分享之系统消息

简介:

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


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

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,
         0  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,如需转载请自行联系原作者
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
安全 关系型数据库 MySQL
如何将数据从MySQL同步到其他系统
【10月更文挑战第17天】如何将数据从MySQL同步到其他系统
2208 0
|
消息中间件 缓存 弹性计算
纯PHP+MySQL手搓高性能论坛系统!代码精简,拒绝臃肿
本内容分享了一套经实战验证的社交系统架构设计,支撑从1到100万用户的发展,并历经6次流量洪峰考验。架构涵盖客户端层(App、小程序、公众号)、接入层(API网关、负载均衡、CDN)、业务服务层(用户、内容、关系、消息等服务)、数据层(MySQL、Redis、MongoDB等)及运维监控层(日志、监控、告警)。核心设计包括数据库分库分表、多级缓存体系、消息队列削峰填谷、CQRS模式与热点数据动态缓存。同时提供应对流量洪峰的弹性伸缩方案及降级熔断机制,并通过Prometheus实现全链路监控。开源建议结构清晰,适合大型社交平台构建与优化。
640 11
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。
1003 2
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
947 17
|
关系型数据库 MySQL Linux
CentOS 7系统下详细安装MySQL 5.7的步骤:包括密码配置、字符集配置、远程连接配置
以上就是在CentOS 7系统下安装MySQL 5.7的详细步骤。希望这个指南能帮助你顺利完成安装。
3564 26
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
674 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
Ubuntu 关系型数据库 MySQL
在Ubuntu系统的Docker上安装MySQL的方法
以上的步骤就是在Ubuntu系统的Docker上安装MySQL的详细方法,希望对你有所帮助!
1554 12
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
|
存储 SQL 关系型数据库
服务器数据恢复—云服务器上mysql数据库数据恢复案例
某ECS网站服务器,linux操作系统+mysql数据库。mysql数据库采用innodb作为默认存储引擎。 在执行数据库版本更新测试时,操作人员误误将在本来应该在测试库执行的sql脚本在生产库上执行,导致生产库上部分表被truncate,还有部分表中少量数据被delete。
442 25

推荐镜像

更多