<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          三行Java代碼提升接口性能600倍

          共 2140字,需瀏覽 5分鐘

           ·

          2024-03-24 21:30

          來源:juejin.cn/post/7322156759443144713

          推薦:https ://t.zsxq.com/16HjsdjFc

          背景

          業(yè)務(wù)在群里反饋編輯結(jié)算單時(shí)有些賬單明細(xì)查不出來,但是新建結(jié)算單可以,我第一反應(yīng)是去測(cè)試環(huán)境試試有沒有該問題,結(jié)果發(fā)現(xiàn)沒任何問題?。?!

          然后我登錄生產(chǎn)環(huán)境編輯業(yè)務(wù)反饋有問題的結(jié)算單,發(fā)現(xiàn)查詢接口直接504網(wǎng)關(guān)超時(shí)了,此時(shí)心里已經(jīng)猜到是代碼性能問題導(dǎo)致的,接來下就把重點(diǎn)放到排查接口超時(shí)的問題上了。

          歡迎加入 https://t.zsxq.com/16OHFdQff。

          08e16a606d6c3be9c0e6d0c6934477a9.webp

          問題排查

          遇到生產(chǎn)問題先查日志是基本操作,登錄阿里云的日志平臺(tái),可以查到接口耗時(shí)竟然高達(dá)469245毫秒!

          這個(gè)結(jié)算單關(guān)聯(lián)的賬單數(shù)量也就800多條,所以可以肯定這個(gè)接口存在性能問題。

          da9effc7620f003ce783823a640b2ef1.webp

          但是日志除了接口耗時(shí),并沒有其他報(bào)錯(cuò)信息或異常信息,看不出哪里導(dǎo)致了接口慢。

          接口慢一般是由如下幾個(gè)原因?qū)е拢?/strong>

          1. 依賴的外部系統(tǒng)慢,比如同步調(diào)用外部系統(tǒng)的接口耗時(shí)比較久
          2. 處理的數(shù)據(jù)過多導(dǎo)致
          3. sql性能有問題,存在慢sql
          4. 有大循環(huán)存在循環(huán)處理的邏輯,如循環(huán)讀取exel并處理
          5. 網(wǎng)絡(luò)問題或者依賴的中間件比較慢
          6. 如果使用了鎖,也可能由于長(zhǎng)時(shí)間獲取不到鎖導(dǎo)致接口超時(shí)

          當(dāng)然也可以使用 arthas 的 tracehttps://arthas.aliyun.com/doc/trace.html命令分析哪一塊比較耗時(shí)。

          由于安裝arthas有點(diǎn)麻煩,就先猜測(cè)可能慢sql導(dǎo)致的,然后就登錄阿里云RDS查看了慢sql監(jiān)控日志。

          d8ddc072e64da4ed12b234e16922713b.webp

          好家伙一看嚇一跳,sql耗時(shí)竟然高達(dá)66秒,而且執(zhí)行次數(shù)還挺多!

          我趕緊把sql語(yǔ)句放到數(shù)據(jù)庫(kù)用explain命令看下執(zhí)行計(jì)劃,分析這條sql為啥這么慢。

                
                EXPLAIN SELECT DISTINCT(bill_code) FROM `t_bill_detail_2023_4` WHERE  
          (settlement_order_code IS NULL OR settlement_order_code = 'JS23122600000001');

          分析結(jié)果如下:

          db7b472db0807584591f57517cd4583d.webp

          如果不知道explain結(jié)果每個(gè)字段的含義,可以看看這篇文章《EXPLAIN 和 SHOW TABLE STATUS LIKE 里返回的 rows 為什么不準(zhǔn)確?》。

          可以看到掃描行數(shù)達(dá)到了250多萬行,ref已經(jīng)是最高效的const,但是看最后的Extra列 Using temporary 表明這個(gè)sql用到了臨時(shí)表,頓時(shí)心里清楚什么原因了。

          因?yàn)閟ql有個(gè)去重關(guān)鍵字DISTINCT,所以mysql在需要建臨時(shí)表來完成查詢結(jié)果集的去重操作,如果結(jié)果集數(shù)據(jù)量比較小沒有超過buffer,就可以直接在內(nèi)存中去重,這種效率也是比較高的。

          但是如果結(jié)果集數(shù)據(jù)量很大,buffer存不下,那就需要借助磁盤完成去重了,我們都知道操作磁盤相比內(nèi)存是非常慢的,時(shí)間差幾個(gè)數(shù)量級(jí)

          雖然這個(gè)表里的settlement_order_code字段是有索引的,但是線上也有很多settlement_order_code為null的數(shù)據(jù),這就導(dǎo)致查出來的結(jié)果集非常大,然后又用到臨時(shí)表,所以sql耗時(shí)才這么久!

          同時(shí),這里也解釋了為什么測(cè)試環(huán)境沒有發(fā)現(xiàn)這個(gè)問題,因?yàn)闇y(cè)試環(huán)境的數(shù)據(jù)不多,直接在內(nèi)存就完成去重了。

          問題解決

          知道了問題原因就很好解決了,首先根據(jù)SQL和接口地址很快就找到出現(xiàn)問題的代碼是下圖紅框圈出來的地方

          dd792fa9d847b52d2b1a7fd42ac2749d.webp

          可以看到代碼前面有個(gè)判斷,只有當(dāng)isThreeOrderQuery=true時(shí)才會(huì)執(zhí)行這個(gè)查詢,判斷方法代碼如下

          c0ef10824ce0178565c2b5847e06441a.webp

          然后因?yàn)檫@是個(gè)編輯場(chǎng)景,前端會(huì)把當(dāng)前結(jié)算單號(hào)(usedSettlementOrderCode字段)傳給后端,所以這個(gè)方法就返回了true。

          同理,拼接出來的sql就帶了條件(settlement_order_code IS NULL OR settlement_order_code = 'JS23122600000001')。

          682c170ab26e3ca215e3f55114031344.webp

          解決起來也很簡(jiǎn)單,把isThreeOrderQuery()方法圈出來的代碼去掉就行了,這樣就不會(huì)執(zhí)行那個(gè)查詢,同時(shí)也不會(huì)影響原有的代碼邏輯,因?yàn)楹竺鏁?huì)根據(jù)篩選條件再查一次t_bill_detail表。

          改代碼發(fā)布后,再編輯結(jié)算單,優(yōu)化后的效果如下圖:

          f0f0c63e598f5bcf363d3bff6b8e9fad.webp

          只改了三行代碼,接口耗時(shí)就立馬從469245ms縮短到700ms,性能提升了600多倍

          總結(jié)

          感覺壓測(cè)環(huán)境還是有必要的,有些問題數(shù)據(jù)量小了或者請(qǐng)求并發(fā)不夠都沒法暴露出來,同時(shí)以后寫代碼可以提前把sql在數(shù)據(jù)庫(kù)explain下看看性能如何,畢竟能跑就行不是我們的追求??。

          瀏覽 70
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  自拍偷拍第十页 | 操爱| 日韩综合网站 | 国产九九九在线观看 | 久久久精品 |