mysql n 1问题_MySQL N+1 问题

模拟场景

在我们进行处理业务的过程中,经常会遇到查询两个表的场景。如:要求查询文章表下面所有的评论

文章表article

字段名称

类型

说明

id

int

文章主键

title

varchar

文章标题

评论表comment

|字段名称 | 类型 | 说明|

|--|--|--|

|id|int|评论主键

|article_id|int|文章主键

|content|varchar|评论内容

错误示范

//取出文章的ID

$articleList = M('article')->select();

//遍历文章,进行查看文章下面的评论

forearch($articleList as $k=>$v) {

$map['article_id'] = $v['article_id'];

$commentList = M('comment')->where($map)->select();

$articleList[$k]['commnet_list'] = $commentList;

}

这里就会产生一个问题,对数据库的压力会增大。比如article一共有1000条,那么对应的会进行查询10001次的数据库操作。

正确示范

$articleList = M('article')->select();

$articleMap = [];

foreach($articleList as $k=>$v) {

$articleMap[$v['id']] = $v;

}

$articleIds = array_keys($articleMap);

$articleIds = implode(',', $articleIds);

$commentList = M('comment')->where(array('article_id'=>array('in',$articleIds)));

$result = [];

forearch($commentList as $k=>$v) {

$result[$v['article_id']]['id'] = $articleMap[$v['article_id']]['id'];

$result[$v['article_id']]['title'] = $articleMap[$v['article_id']]['title'];

$result[$v['article_id']]['commentList'][]['id'] = $v['id'];

$result[$v['article_id']]['commentList'][]['title'] = $v['title'];

}

# 最后的结果是

$articleAndCommentList = array_values($result) + $articleList;

这里可以看出,虽然代码增加了,但是对MySQL的压力缺减少,只进行了两次sql查询。

为了解决这一弊端,引入了比较经典的MySQL N+1的问题。

什么是N+1?

A对象关联B对象,A对象进行列表展示时需显示B对象的关联属性,这样需要先用一条sql将N个A对象查询出来,再用N条sql将这些对象的关联属性查询出来。违背了减少数据库交互原则,影响性能。

拓展

在较为成熟的PHP框架中如:ThinkPHP、PhalApi、laravel等,都有对如上的动作进行了封装。

PhalAPI 1.4.2

示例

$aMap = $this->getORMDemo()->fetchPairs('id');

$aIds = array_keys($aMap);

$aIds = implode(',', $aIds);

$sql2 = "select * from comment where article_id in ({$aIds})";

$comments= $this->getORMDemo()->queryAll($sql2,[]);

foreach ($comments as $c){

$aId = $c['article_id'];

echo $c['title'], $aMap[$aId]['title'].'
';

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值