• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Mysql解决数据库N+1查询问题

    简介

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

    数据表如下:

    department表

    |id|name|

    user表

    |id|name|department_id|

    需求是得到以下结构的数据:

    [
      {    "id":1,    "name":"test",    "department_id":1,    "department":{      "id":1,      "name":"测试部门"
        }
      }
    ]

    方法一:循环查询

    查询用户列表

    循环用户列表查询对应的部门信息

    $users = $db->query('SELECT * FROM `user`');foreach($users as $user) {
      $users['department'] = $db->query('SELECT * FROM `department` WHERE `id` = '.$user['department_id']);
    }

    该方法查询次数为:1+N(1次查询列表,N次查询部门),性能最低,不可取。

    方法二:连表

    通过连表查询用户和部门数据

    处理返回数据

    $users = $db->query('SELECT * FROM `user` INNER JOIN `department` ON `department`.`id` = `user`.`department_id`');// 手动处理返回结果为需求结构

    该方法其实也有局限性,如果 user 和 department 不在同一个服务器是不可以连表的。

    方法三:1+1查询

    该方法先查询1次用户列表

    取出列表中的部门ID组成数组

    查询步骤2中的部门

    合并最终数据

    代码大致如下:

    $users = $db->query('SELECT * FROM `user`');
    $departmentIds =[ ];foreach($users as $user) {  if(!in_array($user['department_id'], $departmentIds)) {
        $departmentIds[] = $user['department_id'];
      }
    }
    $departments = $db->query('SELECT * FROM `department` WHERE id in ('.join(',',$department_id).')');
    $map = []; // [部门ID => 部门item]foreach($departments as $department) {
      $map[$department['id']] = $department;
    }foreach($users as $user) {
      $user['department'] = $map[$user['department_id']] ?? null;
     }

    该方法对两个表没有限制,在目前微服务盛行的情况下是比较好的一种做法。

    上一篇:MySQL全文索引实现简单版搜索引擎实例代码
    下一篇:mysql 8.0.16 winx64及Linux修改root用户密码 的方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Mysql解决数据库N+1查询问题 Mysql,解决,数据库,N+1,查询,