1. 程式人生 > >資料庫查詢的N+1問題

資料庫查詢的N+1問題

轉載自:https://blog.csdn.net/w05980598/article/details/79647291

簡介

在orm框架中,比如hibernate和mybatis都可以設定關聯物件,比如user物件關聯dept假如查詢出n個user,那麼需要做n次查詢dept,查詢user是一次select,查詢user關聯的dept,是n次,所以是n+1問題,其實叫1+n更為合理一些。

mybatis配置

UserMapper.xml

<resultMap id="BaseResultMap" type="testmaven.entity.User">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="age" jdbcType="INTEGER" property="age" />
    <result column="dept_id" jdbcType="INTEGER" property="deptId" />
    <association property="dept" column="dept_id" fetchType="eager" select="testmaven.mapper.DeptMapper.selectByPrimaryKey" ></association>
  </resultMap>
DeptMapper.xml

<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from dept
    where id = #{id,jdbcType=INTEGER}
  </select>

我們可以看到user通過association中的dept_id關聯了dept,查詢user後,比如查詢到4個user,那麼會執行4次查詢dept;

測試

List<User> list = userMapper.selectByExample(null);

列印jdbc log我們能看到,查詢到4個user,然後執行了4次查詢dept 

 

1+n帶來的問題

查詢主資料,是1次查詢,查詢出n條記錄;根據這n條主記錄,查詢從記錄,共需要n次,所以叫資料庫1+n問題;這樣會帶來效能問題,比如,查詢到的n條記錄,我可能只用到其中1條,但是也執行了n次從記錄查詢,這是不合理的。為了解決這個問題,出現了懶載入

,懶載入就是用到的時候再查詢;我們設定association元素中的fetchType fetchType=lazy

<association property="dept" column="dept_id" fetchType="lazy" select="testmaven.mapper.DeptMapper.selectByPrimaryKey" ></association>

我們再做測試

List<User> list = userMapper.selectByExample(null);
    User u = list.get(0);
    System.out.println(u.getClass());
    System.out.println(u.getName());

jdbc log

 

懶載入 減少了效能消耗,一定程度上緩解了1+n帶來的效能問題

總結

1+n問題是什麼?應該怎樣解決?

1+n是執行一次查詢獲取n條主資料後,由於關聯引起的執行n次查詢從資料;它帶來了效能問題;
一般來說,通過懶載入 可以部分緩解1+n帶來的效能問題