PHP使用array_merge导致内存不足的反思
故事背景
- 从用户喜欢表分批拿到数据,通过array_merge()组装,再批量插入到数据分析表。
- 测试的时候因为数据量小,没有出现问题。随着业务增长,在查询范围内已经超过3万条数据。
- 3万条数据在8核32G的单机上已经提示内存溢出了。
解决问题的思路
- 设计初衷是不全量分析数据,只取查询范围内有喜欢动作的用户
- 尽量减少DB操作,把计算和拼接数据的操作交给程序
- 因为没有考虑到程序的计算也是有上限的,所有解决问题的思路在于上面的1、2保持不变,需要找到一个平衡点。
优化后的思路是:
分批取的同时分批插入,每次插入休眠10毫秒
核心代码如下:
//最近7天喜欢的数据
public static function likeBetweenDuration($begin, $end)
{
$limit = 1000;
$offset = 0;
$users = [];
do {
$sponsorUserIds = self::query()
->selectRaw('userid,createtime')
->distinct()
->whereBetween('createtime', [$begin, $end])
->orderBy('createtime')
->offset($offset)
->limit($limit)
->get()
->toArray();
$beLikedUserIds = self::query()
->selectRaw('"otherUserid",createtime')
->distinct()
->whereBetween('createtime', [$begin, $end])
->orderBy('createtime')
->offset($offset)
->limit($limit)
->get()
->toArray();
$sponsorUserIds = array_column($sponsorUserIds, 'userid');
$beLikedUserIds = array_column($beLikedUserIds, 'otherUserid');
$likesUserIds = array_unique(array_merge($sponsorUserIds, $beLikedUserIds));
$userIds = array_map(function ($value) {
return ['userid' => $value];
}, $likesUserIds);
UserActionRecord::recordBatch($userIds);
echo "推荐算法需要的喜欢\n";
echo 'arrayCount:' . count($userIds) . "\n";
$offset = $offset $limit;
echo '偏移量:' . $offset . "\n";
usleep(10); //休眠10毫秒
} while ($userIds);
return $users;
}
优化前的思路是:
分批从DB中读取,通过array_merge()拼接所有数据,将所有数据通过一条sql批量插入数据库。
核心代码如下:
//分批取值的方法
public static function likeBetweenDuration($begin, $end, $select = 'userid,"otherUserid"')
{
$limit = 200;
$offset = 0;
$users = [];
do {
$thisUsers = self::query()
->selectRaw($select)
->whereBetween('createtime', [$begin, $end])
->orderBy('createtime')
->offset($offset)
->limit($limit)
->get()
->toArray();
$users = array_merge($users, $thisUsers);
$offset = $offset $limit;
} while ($thisUsers);
return $users;
}
//获得所有数据,再去重,插入数据库
$likes = UserRelationSingle::likeBetweenDuration(Utility::recommendCalcTimestamp(), Utility::recommendCalcEndTimestamp());
$sponsorUserIds = array_column($likes, 'userid');
$beLikedUserIds = array_column($likes, 'otherUserid');
$likesUserIds = array_unique(array_merge($sponsorUserIds, $beLikedUserIds));
$userIds = array_map(function ($value) {
return ['userid' => $value];
}, $likesUserIds);
UserActionRecord::recordBatch($userIds);
echo "UserActionRecord 批量记录有喜欢行为的用户:" .
json_encode($userIds) . "\n";
总结
-
优化前的array_merge()一定会随着数据的增多出现内存不足的情况,而优化后的代码就不会。
-
优化后的思路array_merge()每次最多只会处理2千条数据。
思路对比:
-
优化前的思路尝试使用尽量少的sql,减少DB操作,把压力交给程序(PHP函数)去处理,忽略了内存问题。
-
优化后的思路较好的平衡了DB操作和程序之间的平衡关系,分配读取的sql没有变; 之前的一次写入改成了多次写入,规避了内存问题,同时每次DB插入之后休眠10毫秒,减轻DB压力。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanfbbbj
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01