news 2026/5/6 21:19:27

php性能优化之不要在for循环中操作DB

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
php性能优化之不要在for循环中操作DB

如何提高程序运行速度,减轻服务器压力是服务端开发必须面对的一个问题。

简单且朴素的原则:不要在for循环中操作DB,包括关系型数据库和NoSql。

我们应该根据自己的业务场景,在for循环之前批量拿到数据,用尽量少的sql查询批量查到结果。 在for循环中进行数据的匹配组装。

场景说明

  • 业务在多个情景下需要获得用户的详细信息,有点可以通过查询用户表直接获取到,有的需要查询关联关系表获取到,有的只保存了关联的id,并没有单独创建关联关系表,需要单独写获取函数取值。
  • 既然多个场景下需要调用,那么封装成一个公共方法,让多个场景统一调用公共方法是基本的优化思路。
  • 上面提到了复杂的存取值关系,我们需要分析一下,哪些操作是耗时的,耗时的操作如何优化,能否减少sql查询的次数。

举例说明

  • 下面的代码示例,我们封装了 CommonRender 的类,所有可以统一输出的方法都在这里
  • 下面代码标注了优化之前优化之后
  • 优化之前:在每次查询都需要根据保存的id,去数据库查询;如果列表页每次返回30条数据,那这部分就需要30次sql查询。
  • 优化之后:采用的是提前批量取值,又写了一个函数 _renderHobby ,只需要1次sql。
  • 这样就极大的减少了sql查询,提高了程序响应的速度。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

<?php

namespaceApp\Render;

.

.

.

classCommonRenderextendsBaseRender

{

publicstaticfunctionrenderUserinfo($data,$hobbyInfo= [])

{

if(!is_array($data)) {

return[];

}

$ret= [

'uid'=> !isset($data['id']) ? 0 :$data['id'],

'userid'=> !isset($data['userid']) ?'':$data['userid'],

'username'=> !isset($data['username']) ?'':$data['username'],

'usericon'=> !isset($data['usericon']) ? [] :$data['usericon'],

.

.

.

//优化之前

// 'hobby' => !isset($data['hobby']) ? [] : HobbyInfo::getByIds($data['hobby']),

//优化之后

'hobby'=> !isset($data['hobby']) ? [] : self::_renderHobby($data['hobby'],$hobbyInfo),

.

.

.

if(!empty($ret['birth'])) {

$ret['zodiacSign'] = Utility::getZodiacSign($ret['birth']);

}else{

$ret['zodiacSign'] ='';

}

return$ret;

}

protectedstaticfunction_renderHobby($userHobby,$hobbyInfo)

{

$ret= [];

if($userHobby) {

$userHobbyIds=explode(',',$userHobby);

foreach($userHobbyIdsas$key=>$userHobbyId) {

$ret[$key] =$hobbyInfo[$userHobbyId];

}

}

return$ret;

}

//用户列表卡片常用字段

publicstaticfunctionrenderListCardUserinfo($data)

{

.

.

.

}

}

进一步优化

上面的代码已经优化了性能,但是还不够优雅。

获取单用户信息场景比较多,比如编辑,登录,查看单人信息等,这种情况下我还每次都提前批量查询吗?这样的话需要改造的地方太多了。

下面做进一步优化:

在render方法内部封装了一层,如果外部没有传入或传入空数组,自己再查询db获得一次需要的数据源。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

<?php

namespaceApp\Render;

.

.

.

classCommonRenderextendsBaseRender

{

publicstaticfunctionrenderUserinfo($data,$hobbyInfo= [])

{

//区别在这里:批量查询外部传入,减少sql查询次数; 单次查询在render内查一次

$hobbyInfo= !empty($hobbyInfo) ?$hobbyInfo: HobbyInfo::getAllInfo();

if(!is_array($data)) {

return[];

}

$ret= [

'uid'=> !isset($data['id']) ? 0 :$data['id'],

'userid'=> !isset($data['userid']) ?'':$data['userid'],

'username'=> !isset($data['username']) ?'':$data['username'],

'usericon'=> !isset($data['usericon']) ? [] :$data['usericon'],

.

.

.

//优化之前

// 'hobby' => !isset($data['hobby']) ? [] : HobbyInfo::getByIds($data['hobby']),

//优化之后

'hobby'=> !isset($data['hobby']) ? [] : self::_renderHobby($data['hobby'],$hobbyInfo),

.

.

.

if(!empty($ret['birth'])) {

$ret['zodiacSign'] = Utility::getZodiacSign($ret['birth']);

}else{

$ret['zodiacSign'] ='';

}

return$ret;

}

protectedstaticfunction_renderHobby($userHobby,$hobbyInfo)

{

$ret= [];

if($userHobby) {

$userHobbyIds=explode(',',$userHobby);

foreach($userHobbyIdsas$key=>$userHobbyId) {

$ret[$key] =$hobbyInfo[$userHobbyId];

}

}

return$ret;

}

//用户列表卡片常用字段

publicstaticfunctionrenderListCardUserinfo($data)

{

.

.

.

}

}

这样,那些获得单个用户资料的方法就不需要修改了。

1

2

3

4

5

6

7

8

9

10

//编辑用户资料

publicfunctioneditUserInfo(Request$request)

{

$userInfo= UserInfo::editUserById($this->_userid,$request);

return[

'user'=>

CommonRender::renderUserinfo($userInfo)

+ UserInfo::formatCoverAndPickedFootprint($userInfo)

];

}

性能对比

批量获得用户信息对比:性能提升立竿见影。

  • 比如每次取30个用户数据,之前获得爱好,职业,期望部分要查询30次db。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/6 21:16:33

从化工反应器到生物质气化:Fluent流化床欧拉模型在新能源领域的实战应用拓展

Fluent流化床欧拉模型在生物质气化中的高阶应用指南 流化床反应器正经历从传统化工向新能源领域的范式转移。当生物质颗粒在高温气流中翻滚、裂解、气化时&#xff0c;工程师们面对的是一套全新的多物理场耦合难题——颗粒形态不规则、热解反应剧烈、相间传质复杂。这些挑战恰恰…

作者头像 李华
网站建设 2026/5/6 21:14:33

手把手教你用ZYNQ FPGA驱动LMX2571时钟芯片(Verilog SPI代码详解)

从零构建LMX2571时钟芯片的Verilog SPI驱动&#xff1a;ZYNQ FPGA实战指南 在嵌入式系统设计中&#xff0c;精确的时钟信号如同人体的脉搏&#xff0c;决定了整个系统的运行节奏。LMX2571作为TI公司的高性能时钟发生器&#xff0c;广泛应用于通信设备、测试仪器等领域。本文将带…

作者头像 李华
网站建设 2026/5/6 21:11:12

看完这篇,彻底搞懂大模型:30个核心机制全解析

这两年&#xff0c;几乎所有人都在谈大模型。 关于大模型的信息越来越多&#xff0c;但真正清楚的理解&#xff0c;反而越来越少。 很多人对大模型的认知&#xff0c;其实都停留在一种模糊状态&#xff1a; 知道它很强&#xff0c;知道它会写、会答、会编程&#xff0c;甚至…

作者头像 李华
网站建设 2026/5/6 21:10:26

如何用AI智能插件彻底改变你的文献管理:Zotero GPT完全指南

如何用AI智能插件彻底改变你的文献管理&#xff1a;Zotero GPT完全指南 【免费下载链接】zotero-gpt GPT Meet Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-gpt 还在为海量文献整理而烦恼吗&#xff1f;每天面对堆积如山的学术论文&#xff0c;手动提取…

作者头像 李华