首頁 > 軟體

mybatis 查詢方式與效率高低對比

2023-11-03 18:00:24

mybatis查詢方式與效率高低

<!--
     一對一關聯查詢
     select s.id,s.name,s.age,t.name tname  from student s,teacher t where s.tid=t.id;
      -->

    <!--
        關聯的巢狀 Select 查詢
    問題:
        這種方式雖然很簡單,但在大型資料集或大型資料表上表現不佳。這個問題被稱為「N+1 查詢問題」。 概括地講,N+1 查詢問題是這樣子的:
            你執行了一個單獨的 SQL 語句來獲取結果的一個列表(就是「+1」)。
            對列表返回的每條記錄,你執行一個 select 查詢語句來為每條記錄載入詳細資訊(就是「N」)。
    解決:
        MyBatis 能夠對這樣的查詢進行延遲載入,因此可以將大量語句同時執行的開銷分散開來。
        (例如: 我需要teacher這個物件的時候就會進行載入,如果不需要就不會立即載入(延遲載入))
         然而,如果你載入記錄列表之後立刻就遍歷列表以獲取巢狀的資料,就會觸發所有的延遲載入查詢,效能可能會變得很糟糕。
    -->
    <!--  關聯的巢狀 Select 查詢  -->
    <resultMap id="studentMap" type="student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <association property="teacher" column="tid" javaType="teacher" select="selectTeacherById">
        </association>
    </resultMap>

    <select id="findAll" resultMap="studentMap">
        select * from student;
    </select>
    <select id="selectTeacherById" parameterType="int" resultType="teacher"  >
        select * from  teacher where id=#{id};
    </select>


    <!--
        關聯的巢狀  結果對映
        將結果直接對映 到實體類中
        第二種 方式效率比第一種 速度更高
     -->
    <resultMap id="studentMap1" type="student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <association property="teacher" javaType="teacher">
            <id property="id" column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    <select id="selectAll" resultMap="studentMap1">
        select s.id,s.name,s.age,t.name tname ,t.id tid from student s,teacher t where s.tid=t.id;
    </select>

------------------------------------------------------------------
<!--  一對多  關聯巢狀  結果對映    ofType 將資料封裝到指定的泛型  -->
    <resultMap id="teacherMap" type="teacher">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="students" ofType="student" >
            <id property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="age" column="sage"/>
            <result property="tid" column="stid"/>
        </collection>
    </resultMap>
    <select id="selectTeacherById"  parameterType="int"  resultMap="teacherMap">
         select t.id ,t.name,s.id sid,s.name sname,s.age sage,s.tid stid
         from student s ,teacher t
         where s.tid=t.id and t.id=1;
    </select>

mybatis提高查詢效率的方式

快取機制

1 一級快取:

當mysql連續執行兩次select * from table where id =1;第一次會執行sql語句查詢資料庫,然後儲存到sqlsession快取,第二次查詢會先從快取裡查詢,有的話直接返回不會執行sql.

但是如果兩次sql中間增加一次commit操作(insert,delete,update),如:

select * from table where id =1
update table set name = zjw where id =1;
select * from table where id =1

這個時候第一次查詢依然會執行sql查詢資料庫,但是在執行完update後會清空sqlsession裡的快取,原因是避免髒讀,

所以第二次select在快取裡找不到資料,又會執行sql查詢資料庫。

2 二級快取:

二級快取是基於mapper檔案的namaspace,對該mapper的所有sqlsession都共用一個二級快取,如果兩個mapper的namespace一致,則兩個mapper的所有sqlsession共用一個二級快取,

步驟:

在全域性組態檔mybatis-configuration.xml加入

其次在mapper檔案開啟快取 type裡面是快取類。如果不寫是預設的mabatis快取類,自定義快取類必須實現cache介面

需要快取的pojo實體類要實現serializable介面,因為在快取中取出資料對映到pojo類需要反序列化。

不同的兩個sqlsession查詢走二級快取,但是如果其中有一個commit操作,為避免髒讀二級快取還是會被清空。

在每個sql語句上使用useCache=true/false是否使用快取,flushcache=true/false是否重新整理快取 ,在每次的commit後預設重新整理快取。

懶載入

Mybatis中resultmap可以實現高階對映,association一對一,Collection一對多具有延遲載入功能

在collection或association中fetchtype=lazy,即為懶載入

在查詢主表時,不會把子集查出來,直到子集用到的情況才會查出子集。

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com