解決mybatis-plus 查詢耗時慢的問題

mybatis-plus 查詢耗時慢

1、現象

查出30000多條id

然後用

EntityWrapper ew = new EntityWrapper<>();
 ew.in(TableFieldConstant.F_AUTH_RESULT_ID, ids);

查詢會很慢

2、原因

跟瞭一下mybatis-plus源碼

 protected String formatSqlIfNeed(boolean need, String sqlStr, Object... params) {
        if (need && !StringUtils.isEmpty(sqlStr)) {
            if (ArrayUtils.isNotEmpty(params)) {
                for(int i = 0; i < params.length; ++i) {
                    String genParamName = "MPGENVAL" + this.paramNameSeq.incrementAndGet();
                    sqlStr = sqlStr.replace(String.format("{%s}", i), String.format("#{%s.paramNameValuePairs.%s}", this.getParamAlias(), genParamName));
                    this.paramNameValuePairs.put(genParamName, params[i]);
                }
            }
 
            return sqlStr;
        } else {
            return null;
        }
    }

問題出現在

sqlStr = sqlStr.replace(String.format("{%s}", i), String.format("#{%s.paramNameValuePairs.%s}", this.getParamAlias(), genParamName));

對replace 測試 發現當數據量大時替換會很耗時 測試的遍歷瞭30000次拼接從1到30000 替換耗時20多秒

對 apache-commons-lang 的StringUtis.replace測試是耗時7秒多

3、總結

把使用mybaits 批量查詢改為 手寫sql查詢 之後問題解決

使用mybatis-plus批量操作時要謹慎 能寫sql盡量寫sql

這個跟mybatis-plus 的小夥伴提瞭問題後已經解決 可以升級jar版本 3.x

mybatis-plus 處理大數據量太慢

大批量數據插入方法是Mybatis的foreach拼接SQL

我發現不管改成Mybatis Batch提交或者原生JDBC Batch的方法都不起作用,實際上在插入的時候仍然是一條條記錄的插,速度遠不如原來Mybatis的foreach拼接SQL的方法。

// 第一步判斷更新或添加
 String[] splitUserId = userGroup.getUserId().split(",");
 String[] spiltUserName = userGroup.getUserName().split(",");
 if (StringUtils.isBlank(userGroup.getId())) {
  userGroup.setNum(spiltUserName.length);
  userGroupMapper.insert(userGroup);
 } else {
  userGroup.setNum(spiltUserName.length);
  userGroupMapper.updateById(userGroup);
 }
 /* 第二部刪除中間表信息,字段冗餘 */

 Map<String, Object> columnMap = new HashMap<String, Object>();
 columnMap.put("USER_GROUP_ID", userGroup.getId());
 groupUsersService.removeByMap(columnMap);

 /* 第三步,批量保存中間表 */

 if (splitUserId.length != 0) {
  List<GroupUsers> groupUsersList = Lists.newArrayList();
  for (int i = 0; i < splitUserId.length; i++) {
   GroupUsers gu = new GroupUsers();
   gu.setUserId(splitUserId[i]);
   gu.setUserName(spiltUserName[i]);
   gu.setUserGroupId(userGroup.getId());
   groupUsersList.add(gu);
  }
  groupUsersService.saveBatch(groupUsersList);
 }

1、就是這樣的一種情景也很符合大部分的開發場景,可就是1000條數據的情況下用瞭8秒 ,這可能與計算機的性能有很大的關系,但就是如此也不至於用八秒鐘,那麼用戶體驗會很慘的。

2、JDBC連接URL字符串中需要新增一個參數:

rewriteBatchedStatements=true url: jdbc:mysql://192.168.1.143:3306/rt_xxxxxx_test?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true

3、MySQL的JDBC連接的url中要加rewriteBatchedStatements參數,並保證5.1.13以上版本的驅動,才能實現高性能的批量插入。

4、MySQL JDBC驅動在默認情況下會無視executeBatch()語句,把我們期望批量執行的一組sql語句拆散,一條一條地發給MySQL數據庫,批量插入實際上是單條插入,直接造成較低的性能。

隻有把rewriteBatchedStatements參數置為true, 驅動才會幫你批量執行SQL

另外這個選項對INSERT/UPDATE/DELETE都有效

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: