ThinkPHP 6.0+ 已彻底移除 partition 分表配置支持,5.x 版本中该配置实际无效;分表逻辑需手动计算表名,推荐封装独立工具类实现归档表路由,并根据查询条件精准定位目标表,避免全表扫描。

ThinkPHP 官方从 6.0 开始已彻底移除 partition 分表配置支持,5.x 版本虽保留字段但实际无效。所谓“归档表”或“历史数据冷热分离”,不是框架内置能力,而是必须手动实现的业务逻辑。
分表逻辑必须自己算表名,不能依赖 $model->partition
partition 配置在 TP6+ 中完全失效,TP5.x 即使写上也不会触发任何行为。你看到的文档残留、旧博客示例(如 $this->partition['type'] === 'year')仅适用于极老的 TP3.2,且早已被弃用。
- 常见错误现象:配置了
'partition' => ['type' => 'year', 'field' => 'create_time'],但查询仍走主表,日志/SQL 中看不到后缀 - 正确做法是显式计算:比如按年归档,就用
date('Y', $timestamp)拼出order_2024、order_2025 - 不要重写
save()或select()方法去“自动切换”,容易和模型生命周期冲突(如软删除、时间戳自动填充会失效)
推荐封装一个独立工具类:
class ArchiveTable
{
public static function getOrderTable($time)
{
return 'order_' . date('Y', $time);
}
<pre class="brush:php;toolbar:false;">public static function getLogTable($dateString)
{
return 'sys_log_' . date('Ym', strtotime($dateString));
}}
然后在业务中直接调用:Db::table(ArchiveTable::getOrderTable($createTime))->insert($data)
冷热分离查询要避免全表扫描,别用 foreach + table() 硬扫
很多教程教你在控制器里写循环查所有归档表:
立即学习“PHP免费学习笔记(深入)”;
$tables = ['order_2023', 'order_2024', 'order_2025'];
foreach ($tables as $table) {
$list = Db::table($table)->where('status', 1)->select();
// ... 合并结果
}这看似能查到全部数据,但问题严重:
- 每次请求发起 N 次 SQL,连接开销翻倍
- 无法使用数据库索引优化(各表独立执行,无联合计划)
- 无法做
ORDER BY ... LIMIT分页,结果集合并后分页不准 - 时间范围明确时(如只查 2024 年订单),却仍扫 2023/2025 表
正确做法是根据查询条件反推目标表:
- 查
create_time BETWEEN '2024-01-01' AND '2024-12-31'→ 只查order_2024 - 查
create_time > '2025-03-01'→ 只查order_2025(若已建order_2026则也需判断)
如果确实需要跨年聚合(如统计近 3 年总金额),应改用原生 SQL 的 UNION ALL,由数据库完成合并:
SELECT SUM(total) FROM (
SELECT total FROM order_2024 WHERE status = 1
UNION ALL
SELECT total FROM order_2025 WHERE status = 1
) AS t归档表命名和建表必须提前规划,别等数据爆了再补
- 表名后缀建议统一用固定长度格式,如
log_202403(年月)、trade_y2025(年),避免log_2024_3这类不规则命名导致排序/匹配失败 - 提前建好未来 6–12 个月的空表(用
CREATE TABLE ... LIKE复制结构),防止运行时建表阻塞请求或引发并发冲突 - 不要在
getCurrentTable()里实时SHOW TABLES+CREATE TABLE,TP 的模型初始化早于请求上下文,容易在 CLI 或队列中触发异常 - 若用定时任务建表,确保其与业务写入逻辑隔离——例如每月 1 号凌晨 2 点建下月表,而业务代码只负责读写,不负责建
真正难的不是算表名,而是让整个链路保持一致性:路由参数、缓存 key、日志记录、数据迁移脚本、监控告警,都要对得上同一套分表规则。一旦某处写死 order 主表,或缓存没带年份后缀,冷热数据就会混在一起,排查成本远高于初期多写几行计算逻辑。



















