分块处理数据

项目中经常碰到一些慢 sql,sql 本身没有继续优化的空间,该使用的索引也都用上了。想要继续优化,就要考虑每次分块处理,也就是把原先大的结果集分割成一个个的小块,类似于 Laravelchunk 方法。

这里基于我司的 PHP 框架写了个简单的使用方式,通过传入 sql 的方式把 sql 中的占位符 ? 号替换为 where in 条件中的子集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
trait getDataInChunkTrait
{
/**
* 分块获取数据:目前只支持对 sql 中单个 IN 条件的分块获取
*
* @param array $list 要放入 where 条件 IN 的集合
* @param string $sql 执行的sql,其中的 ? 会被 list 子集替换
* @param int $size
*
* @return array
*/
public function getDataInChunk(array $list, string $sql, int $size = 500): array
{
$result = [];
/** @var Model $model */
$model = M('');
foreach (array_chunk($list, $size) as $sub_list) {
$sub_str = implode(',', $sub_list);
$run_sql = str_replace('?', $sub_str, $sql);
$result = array_merge($result, $model->select($run_sql) ?: []);
}
return $result;
}
}

可以这么使用

1
2
3
4
5
6
7
$sql    = "SELECT order_id, max(create_time) as running_time
FROM order_operate
WHERE
order_id IN (?)
AND after_status = 4
GROUP BY order_id";
$orders = $this->getDataInChunk($orders, $sql, 200);