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

 更新时间:2019年07月10日 08:37:08   作者:步履不停  
在本篇文章里小编给大家分享了关于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 5.5.56免安装版配置方法

    mysql 5.5.56免安装版配置方法

    这篇文章主要介绍了mysql 5.5.56免安装版配置方法,本文通过文字实例代码相结合的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-06-06
  • 如何查本地mysql的username和密码及更新密码几种方式

    如何查本地mysql的username和密码及更新密码几种方式

    这篇文章主要介绍了光宇如何查找本地MySQL数据库的用户名和密码,包括查看当前用户、列出所有用户、重置密码以及检查配置文件,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-11-11
  • centos7利用yum安装mysql 8.0.12

    centos7利用yum安装mysql 8.0.12

    这篇文章主要为大家详细介绍了centos7利用yum安装mysql 8.0.12,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • MySQL数据表分区策略及优缺点分析

    MySQL数据表分区策略及优缺点分析

    项目开发中,随着数据库数据量越来越大,单个表中数据太多,从而导致查询速度变慢,而且由于表的锁机制导致应用操作也受到严重影响,出现了数据库性能瓶颈。因此我们需要考虑分表与分区,MySQL分表分区就是为了解决大数据量导致MySQL性能低下的问题。
    2021-05-05
  • 阿里云ECS云服务器(linux系统)安装mysql后远程连接不了(踩坑)

    阿里云ECS云服务器(linux系统)安装mysql后远程连接不了(踩坑)

    这篇文章主要介绍了阿里云ECS云服务器(linux系统)安装mysql后远程连接不了(踩坑),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • 实现MySQL数据库锁的两种方式

    实现MySQL数据库锁的两种方式

    今天我们就来聊一聊数据库的锁,实现数据库锁的两种方式,一个是实现乐观锁的方式,一个是实现悲观锁的实现方式,文中的代码示例介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • MySql常用操作SQL语句汇总

    MySql常用操作SQL语句汇总

    这篇文章主要介绍了MySql常用操作SQL语句汇总,本文讲解了增加、删除、查询、修改等常用SQL语句实例,需要的朋友可以参考下
    2015-03-03
  • MySQL递归查询的几种实现方法

    MySQL递归查询的几种实现方法

    本文主要介绍了MySQL递归查询的几种实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-10-10
  • MySQL基础入门教程之事务

    MySQL基础入门教程之事务

    事务主要用于处理操作量大,复杂度高的数据,下面这篇文章主要给大家介绍了关于MySQL基础入门教程之事务的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • MySQL rownumber SQL生成自增长序号使用介绍

    MySQL rownumber SQL生成自增长序号使用介绍

    MySQL 几乎模拟了 Oracle,SQL Server等商业数据库的大部分功能,函数。但很可惜,到目前的版本(5.1.33)为止,仍没有实现ROWNUM这个功能
    2011-10-10

最新评论