MySQL案例分享之系統訊息,mysql案例分享

來源:互聯網
上載者:User

MySQL案例分享之系統訊息,mysql案例分享

 從前有個大師,率領一群徒弟,為客戶做了一個軟體系統。某天,客戶提出了一個新的需求,向系統中的所有使用者發送系統訊息。由於當時系統剛上線不久,系統中的使用者也就幾十個。大師為了考驗自己的徒弟,便將該需求分配給他的徒弟,要求每個人都做一套方案出來,於是便有了下面的故事。


    徒弟們接收到該項任務後,每個人都想到了先建一張系統訊息表,每次發送系統訊息時,將資料儲存在詞表中,使用者就能從該表中讀取他個人的系統訊息。使用者資訊表的模型如下:


    基於上面的資料庫模型,徒弟們分別作了不同的實現方案,如下:


    實現方案一:


    小A是個急性子,領到任務後。立即開始了他的編程思路:將系統中的所有使用者都取出來,然後遍曆所有的使用者,每次迭代時插入一條系統訊息。虛擬碼如下:


1234567 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的虛擬碼如下:

1234567 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語句如下:


123456789 <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>


  虛擬碼如下:


12345678 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設計如下:


123456789101112131415161718 <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】毫秒


    上面的故事,便是我們在開發中經常遇到的情境,要實現系統中的一個功能時,往往有很多種方法,最先實現的,代碼最簡便的並不一定是效率最好的。代碼本身就是一個黑盒子,不要考慮程式的現有效能,更要考慮好程式的擴充性能。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.