提交 ff3a7aae authored 作者: qhz's avatar qhz

【开发】分表功能优化-20240920-hyperf版本.md

上级 27ae8b3f
# 前提
基于 [分表功能开发(初步)](./分表功能开发(初步)-hyperf版本.md) 缺陷。只能应付于简单的 Model 操作行为
```
VirtualRelation::where( 'brand_id', $brand_id )
->where( 'virtual_sn', $this->codeBaseInfo[ 'virtual_sn' ] )
->where( 'status', 1 )
->count();
```
但对于 联表的情况
```
WarehousingCode::query()
->leftJoin('fch_warehousing as w','fch_warehousing_code.warehousing_sn', '=', 'w.warehousing_sn')
->where('fch_warehousing_code.brand_id', $brandId)
->where('w.brand_id', $brandId)
->get();
// 或者
// 出库检查
$codeQuery = OutWarehousingCode::query()
->where( 'fch_out_warehousing_code.brand_id', $this->brandId )
->where( 'fch_out_warehousing.out_warehousing_from_id', $this->dealerId )
->where( 'fch_out_warehousing.brand_id', $this->brandId )
->leftJoin('fch_out_warehousing', 'fch_out_warehousing_code.out_warehousing_sn', '=', 'fch_out_warehousing.out_warehousing_sn');
```
如果两个表同时需要分表的情况下,这样 第一版的方案就不生效. 获取 如果 where 中写 `表名.xx`. 这样分表的情况下会指向原表,直接就报错了
# 优化点
## 依赖包
[hyperf/database]() - v2.2.0 版本
## Hyperf\Database\Model\Model 修改
```
// 增加 分表数据数组
protected $shardingTableInfo = [];
// 用于 在 app Model 层进行设置。这样就可以提供自定义分表数据
public function setShardingTableInfo($shardingData)
{
$this->shardingTableInfo = $shardingData;
return $this;
}
// getQueryGrammar() - 指向SQL 生成的实例
// shardingTableInfo() 方法 - 为分表数据添加方法
protected function newBaseQueryBuilder()
{
$connection = $this->getConnection();
if (!empty($this->shardingTableInfo)) {
$connection->getQueryGrammar()->shardingTableInfo($this->shardingTableInfo);
}
return new QueryBuilder($connection, $connection->getQueryGrammar(), $connection->getPostProcessor());
}
```
## Hyperf\Database\Grammar 修改
```
// 分表数据
protected $shardingTableInfo = [];
// 添加分表数据
public function shardingTableInfo($data)
{
$this->shardingTableInfo = $data;
return $this;
}
// 表名统一处理方法
public function wrapTable($table)
{
if (! $this->isExpression($table)) {
if (!empty($this->shardingTableInfo)) {
$table = $this->setShardingTableInfo($table);
}
return $this->wrap($this->tablePrefix . $table, true);
}
return $this->getValue($table);
}
// 分表数据处理
private function setShardingTableInfo($table)
{
if (!empty($this->shardingTableInfo)) {
if (stripos($table, ' as ') !== false) {
$pos = stripos($table, ' as ');
$preTable = substr($table, 0, $pos);
if (isset($this->shardingTableInfo[$preTable])) {
return $this->shardingTableInfo[$preTable].substr($table, $pos);
}
return $table;
}
return isset($this->shardingTableInfo[$table]) ? $this->shardingTableInfo[$table] : $table;
}
}
```
## App\Model\Model
```
// 所有分表的数据,写入
public function __construct()
{
$brandAuth = get_auth_brand();
if ($brandAuth) {
$brandId = $brandAuth->brandId();
$this->setShardingTableInfo([
$this->getTable() => $this->getTable() . '_' . $brandId, 'fch_warehousing' => 'fch_warehousing_111'
]);
}
parent::__construct();
}
```
## 最终效果
```
WarehousingCode::query()
->leftJoin('fch_warehousing as w','fch_warehousing_code.warehousing_sn', '=', 'w.warehousing_sn')
->where('fch_warehousing_code.brand_id', $brandId)
->where('w.brand_id', $brandId)
->toSql();
```
没有分表的情况
```
select * from `ydd_fch_warehousing_code` left join `ydd_fch_warehousing` as `ydd_w` on `ydd_fch_warehousing_code`.`warehousing_sn` = `ydd_w`.`warehousing_sn` where `ydd_fch_warehousing_code`.`brand_id` = ? and `ydd_w`.`brand_id` = ? and `ydd_fch_warehousing_code`.`deleted_at` is null
```
开启分表后的情况
```
select * from `ydd_fch_warehousing_code_1111` left join `ydd_fch_warehousing_111` as `ydd_w` on `ydd_fch_warehousing_code_1111`.`warehousing_sn` = `ydd_w`.`warehousing_sn` where `ydd_fch_warehousing_code_1111`.`brand_id` = ? and `ydd_w`.`brand_id` = ? and `ydd_fch_warehousing_code_1111`.`deleted_at` is null
```
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论