下面是一个分表聚合助手类的推荐实现方式,你可以将其放在 app/model/TaskRecord.php
或单独新建一个 app/model/ShardingHelper.php
文件,适用于所有类似分表模型(如 TaskRecord、StarRecord)。
分表聚合助手(通用版)
namespace app\model;
use support\Db;
use Illuminate\Support\Collection;
class ShardingHelper
{
/**
* 获取所有分表表名
* @param string $baseTableName 例如 'ss_task_records'
* @param int $shardCount
* @return array
*/
public static function getAllShardTables($baseTableName, $shardCount = 16)
{
$tables = [];
for ($i = 0; $i < $shardCount; $i++) {
$tables[] = "{$baseTableName}_{$i}";
}
return $tables;
}
/**
* 跨所有分表聚合查询
* @param string $baseTableName
* @param callable $queryCallback function($queryBuilder, $tableName)
* @param int $shardCount
* @return Collection
*/
public static function unionAll($baseTableName, callable $queryCallback, $shardCount = 16)
{
$all = collect();
foreach (self::getAllShardTables($baseTableName, $shardCount) as $table) {
$query = Db::table($table);
$result = $queryCallback($query, $table);
if ($result instanceof \Illuminate\Support\Collection) {
$all = $all->merge($result);
} elseif (is_array($result)) {
$all = $all->merge($result);
}
}
return $all;
}
}
使用示例
1. 查询所有分表中 user_id in [1,2,3] 的任务
use app\model\ShardingHelper;
$userIds = [1,2,3];
$allRecords = ShardingHelper::unionAll('ss_task_records', function($query) use ($userIds) {
return $query->whereIn('user_id', $userIds)->get();
});
2. 查询所有分表的任务总数
$total = ShardingHelper::unionAll('ss_task_records', function($query) {
return $query->count();
})->sum();
3. StarRecord 跨分表查询
$allStars = ShardingHelper::unionAll('ss_star_records', function($query) {
return $query->where('type', 'earn')->get();
});
说明
- 你可以把
ShardingHelper
放在app/model/
目录,所有分表模型都能用。 - 只需传入基础表名(如 ‘ss_task_records’),即可跨所有分表聚合。
- 回调里用
$query
写任何你想要的查询,返回 Collection 或数组即可。