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

          記一次IN語(yǔ)句造成的Hibernate QueryPlanCache內(nèi)存泄漏排查和解決辦法

          共 1563字,需瀏覽 4分鐘

           ·

          2023-07-11 12:27

          如果您使用了Hibernate或Spring data jpa,且SQL中使用了IN語(yǔ)句,且每過(guò)一段時(shí)間JVM就拋OOM異常,那么這篇文章可能對(duì)您有用。

          1.問(wèn)題現(xiàn)象

          每過(guò)三四天時(shí)間,JVM就拋出OOM異常,后臺(tái)進(jìn)程掛掉,前端無(wú)法訪問(wèn)。

          2.問(wèn)題排查

          首先,查找一下后臺(tái)進(jìn)程的進(jìn)程號(hào)

              ps -ef | grep "程序名"
            

          然后,使用jmap命令生成內(nèi)存鏡像文件

               jmap -dump:live,format=b,file=heap.hprof 4447
            

          最后,使用 MAT 對(duì)內(nèi)存鏡像文件進(jìn)行分析,分析結(jié)果如下圖所示:

          e13d54ab4a9c244268b5d92c6b38c640.webp

          從Problem Suspect 1 中可以看出一個(gè)SessionFactoryImpl類型的實(shí)例占用了93.14%的內(nèi)存。點(diǎn)擊Details,可以看到SessionFactoryImpl類中有一個(gè)queryPlanCache對(duì)象,占用了大量的內(nèi)存。

          fb925994b04457e2afce9c7d1e0f06c3.webp

          百度了一下queryPlanCache內(nèi)存泄漏,找了一篇和我問(wèn)題相似的文章 《Hibernate sessionFactoryImpl QueryPlanCache 內(nèi)存過(guò)大導(dǎo)致內(nèi)存泄漏》 。文章提到了QueryPlanCache會(huì)緩存sql,以便于后邊的相同的sql重復(fù)編譯,如果in后的參數(shù)不同,hibernate會(huì)把其當(dāng)成不同的sql進(jìn)行緩存,從而緩存大量的sql導(dǎo)致heap內(nèi)存溢出。

          2.解決方案

          第一種方法是添加配置,現(xiàn)在緩沖的sql數(shù)量最大為64(但是我用的spring 1.57.release版本添加該配置沒(méi)有用)

              spring:
              
          jpa:
          ? properties:
          ? ? hibernate:
          ? ? ? query:
          ? ? ? ? plan_cache_max_size: 64
          ? ? ? ? plan_parameter_metadata_max_size: 32

          所以,我對(duì)SQL進(jìn)行了改寫(xiě),之前我的SQL邏輯是這樣的

              # 1.從TOPIC_TOPIC_TYPE表中將帖子類型為1的帖子ID找出來(lái)
              
          SELECT DISTINCT t.topic_id FROM TOPIC_TOPIC_TYPE t WHERE t.type_id=1
          # 2.從TOPIC表中按帖子ID進(jìn)行查詢
          SELECT * FROM TOPIC t WHERE t.id IN ?;

          使用子查詢進(jìn)行優(yōu)化,優(yōu)化后沒(méi)有再出現(xiàn)內(nèi)存泄漏問(wèn)題。

              SELECT * FROM TOPIC WHERE id IN (
              
          SELECT DISTINCT topic_id FROM TOPIC_TOPIC_TYPE WHERE type_id=1
          );

          但是后面使用EXPALIN發(fā)現(xiàn),IN語(yǔ)句走的是全表掃描,性能比較低,所以又用JOIN進(jìn)行了優(yōu)化。

              SELECT * FROM TOPIC t1 JOIN TOPIC_TOPIC_TYPE t2 ON t1.id=t2.topic_id AND t2.type_id=1;
            
          瀏覽 267
          點(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>
                  欧美精品18 | 日韩免费黄色 | 人人艹大香蕉 | 超拍自碰| 操逼在线观看视频 |