各位用户为了找寻关于Mysql解决数据库N+1查询问题的资料费劲了很多周折。这里教程网为您整理了关于Mysql解决数据库N+1查询问题的相关资料,仅供查阅,以下为您介绍关于Mysql解决数据库N+1查询问题的详细内容
简介
在orm框架中,比如hibernate和mybatis都可以设置关联对象,比如user对象关联dept 假如查询出n个user,那么需要做n次查询dept,查询user是一次select,查询user关联的 dept,是n次,所以是n+1问题,其实叫1+n更为合理一些。
mybatis配置
UserMapper.xml
? 1 2 3 4 5 6 7<
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|
需求是得到以下结构的数据:
? 1 2 3 4 5[
{
"id"
:1,
"name"
:
"test"
,
"department_id"
:1,
"department"
:{
"id"
:1,
"name"
:
"测试部门"
}
}
]
方法一:循环查询
查询用户列表
循环用户列表查询对应的部门信息
? 1 2 3$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次查询部门),性能最低,不可取。
方法二:连表
通过连表查询用户和部门数据
处理返回数据
? 1$users = $db->query(
'SELECT * FROM `user` INNER JOIN `department` ON `department`.`id` = `user`.`department_id`'
);// 手动处理返回结果为需求结构
该方法其实也有局限性,如果 user 和 department 不在同一个服务器是不可以连表的。
方法三:1+1查询
该方法先查询1次用户列表
取出列表中的部门ID组成数组
查询步骤2中的部门
合并最终数据
代码大致如下:
? 1 2 3 4 5 6 7 8 9 10 11$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
;
}
该方法对两个表没有限制,在目前微服务盛行的情况下是比较好的一种做法。