TP6下使用chunk分块批量处理数据时,使用多字段分组时错误
数据量太大,使用TP6中chunk分块批量处理数据,而且需要使用多字段分组后批量处理。
问题分析:
使用 mysql 原生查询后,发现分组后的数据量有132298 rows。
1 |
select goods_id,goods_type,stu_id from kk_stu_node_progress where goods_type = 6 group by goods_id,goods_type,stu_id order by stu_id; |
使用chunk进行批量处理,发现一共处理了130398 rows。一共少处理了1900 行数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$total = Db::table('table_name')->field('concat_ws(",",goods_id,goods_type,stu_id) as kk') ->where('goods_type', 6) ->group('goods_id,goods_type,stu_id') ->select() ->toArray(); $total = array_column($total, 'kk'); Db::table('table_name')->field('goods_id,goods_type,stu_id')->where('goods_type', 6) ->group('goods_id,goods_type,stu_id')->chunk(100, function ($nodes) use (&$total) { foreach ($nodes as $node) { $value = $node['goods_id'] . ',' . $node['goods_type'] . ',' . $node['stu_id']; $total = array_diff($total, [$value]); file_put_contents(app_path('..') . 'data-1.txt', json_encode($node) . PHP_EOL, FILE_APPEND); } }, 'stu_id', 'asc'); file_put_contents(app_path('..') . 'data-1-diff.sql', json_encode($total) . PHP_EOL, FILE_APPEND); |
查看 chunk 源码,并打印关键逻辑
可以看出,chunk中的第二次开始查询下一批数据时,是根据 $lastId 来进行了排序后查找,chunk 这个方法,传入的分组条件,也就是 $column ,最好是一个确定唯一的条件。默认会使用主键。像这样如果多字段group by后,存在多个部分字段重复的情况,也就不建议使用 chunk 方法了。
解决办法:
1 2 3 4 5 6 7 8 9 10 11 12 |
$total = Db::table('table_name')->field('goods_id,goods_type,stu_id') ->where('goods_type', 6) ->group('goods_id,goods_type,stu_id') ->select() ->toArray(); while (!empty($total)) { //每次取出100个 $_sub = array_splice($total, 0, 100); foreach ($_sub as $node) { //处理数据 } } |
近期评论