# 分表 **Repository Path**: laravel-admin/sharding ## Basic Information - **Project Name**: 分表 - **Description**: 基于模型声明的 Hyperf 逻辑分表组件:支持按时间(年/月/日)、按容量(固定 ID 段)自动切表,提供透明 CRUD、分页、聚合、注册表与历史数据自动回填。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-02 - **Last Updated**: 2026-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Hyperf 声明式分表(laraveladmin/sharding) Hyperf 模型声明式逻辑分表:内置 `time`(年 / 月 / 日)与 `capacity`(固定 ID 段,写满自动切表)两种模式,提供透明 CRUD、分页、聚合、注册表与自动回填。按年分表:`$shardUnit='year'` + `$shardTable='..._{Y}'`;只写 unit 时默认模板会自动推导年表。 > 状态:MVP。`capacity` 模式(`logs` 使用)已实现并通过测试;`time` 模式为可用基础版;`groupBy` / `distinct`、自定义 driver、自动 schema 变更属于后续增强。 ## 安装与迁移 ```bash composer require laraveladmin/sharding # 1) 发布配置 + 两份迁移到应用目录 php bin/hyperf.php vendor:publish laraveladmin/sharding # 2) 执行迁移(本仓库使用 migrate:all;Hyperf 标准 migrate 亦可) php bin/hyperf.php migrate:all ``` - 包内迁移源文件:`vendor/laraveladmin/sharding/migrations/`(开发副本:`packages/sharding/migrations/`)。 - `vendor:publish` 会把两份迁移复制到 `database/migrations/2026/`;若目标文件已存在会跳过,需覆盖时加 `--force`。若你的应用迁移目录不同,从上述路径手动复制。 - 也可跳过迁移,执行 `php bin/hyperf.php shard:install` 幂等建表(等价 DDL 兜底)。 - 开发期可在本仓库 `server/composer.json` 用 `path` repository 指向 `../packages/sharding`(当前接入方式)。 开发副本/本仓库已提交迁移到 `server/database/migrations/2026/`;其他项目从 `vendor` 或 `vendor:publish` 获取。 默认 `config/sharding.php` 的 `models` 为空/注释,**不硬编码任何模型或数据表**;优先在模型上用 `$shardMode` / `$shardCapacity` / `$shardTable` 声明。 ## 模型声明 ```php use Hyperf\Database\Model\SoftDeletes; use LaravelAdmin\Sharding\Concerns\Shardable; class Log extends Model { use Shardable; use SoftDeletes; protected string $shardMode = 'capacity'; protected int $shardCapacity = 10_000_000; protected string $shardTable = 'logs_{seq}'; protected string $shardIdStrategy = 'range'; protected string $shardKey = 'created_at'; } ``` `logs` 已接入,默认 `SHARDING_ENABLED=false`;完成迁移(或 `shard:install`)→ `shard:create` → `shard:activate` 后再打开。 ## 内部模型 注册表 / 回填记录的数据查询统一走 Eloquent 模型,不用 `Db::table()`: | 表 | 模型 | |---|---| | `shard_registries` | [`LaravelAdmin\Sharding\Model\ShardRegistry`](src/Model/ShardRegistry.php)(`SoftDeletes`) | | `shard_backfills` | [`LaravelAdmin\Sharding\Model\ShardBackfill`](src/Model/ShardBackfill.php) | - 表名 / 连接由 `sharding.registry_table`、`sharding.backfill_table`、`sharding.registry_connection` 配置,模型动态取。 - 数据 CRUD 走模型;DDL、`information_schema` 盘点、动态分表 `MAX(id)` 仍使用连接对象(这些不是注册表数据查询)。 ## 命令 - `shard:install`:创建 `shard_registries` / `shard_backfills` - `shard:create {model} --seq=N`:预建容量分表(pending) - `shard:activate {model} [--seq=N]`:激活写表 / 封旧表 - `shard:backfill {model} [--auto] [--dry-run]`:批量回填(游标续跑) - `shard:backfill:status {model}`:回填进度 - `shard:status {model} [--with-trashed]`:分表 / 水位 - `shard:prune {model} --keep=N [--dry-run] [--force]`:手动清理旧容量表 - `shard:sync-registry {model}`:注册表与物理表漂移报告 ## 行为与限制 - 容量模式按 ID 段计数(含已删除 / 软删除),每表 ≤ capacity;封表前预留安全余量。 - 写切后新数据只写分表,不提供回滚 / 双写 / 反向合并。 - `created_at` 不参与容量模式选表;按时间筛选需扫描全部 active + readonly 表。 - `ORDER BY id` 可逐表取满即停;其它排序字段需归并全部相关表。 - 聚合:`sum` / `count` / `min` / `max` / `avg` 按分片合并,`avg` 用总量重算;`groupBy` / `distinct` 尚未实现。 - 回填:每批一次 SELECT + 每个目标表一条多值 INSERT + 一次游标更新;支持断点续跑。 - 旧表(`shard_table = base_table`)不进入普通查询,不自动删除 / 归档;回填期间按 `id > cursor` 水位并入。 - 自定义 driver 接口已预留,但运行时不接管自定义模式(会显式报错)。 - 激活 / 回填的分布式锁为 P1;MVP 未加锁,多 worker 同时首次写 / 回填需先人工串行。 ## 测试 本仓库: 包测试(在任意已安装本包的 Hyperf 应用中运行;本仓库用 server 容器): ```bash docker compose exec -T server vendor/bin/pest ../packages/sharding/tests ``` 本仓库 `Log` 接入回归: ```bash docker compose exec -T server vendor/bin/pest --test-directory=test test/Unit/Sharding/ShardingLogIntegrationTest.php ```