laravel 8实现 订单表按月份水平分表

本文介绍了一个PHP实现的按月分表的 Trait,用于动态创建和管理分表,确保冷热数据分离。在订单模型中应用此 Trait 后,可以自动处理分表操作。文章强调了分表策略的适用场景,如根据数据量进行分表,但也提醒注意避免因数据分布不均导致的资源浪费。同时,提到了取模分表作为更通用的策略。
摘要由CSDN通过智能技术生成

实现思路:

1.设计基础表orders

2.通过后台代码创建今年6月份订单表:order_202206,今年7月份订单表:order_202207...

创建表的时候需要进行判断,如果表存在,则不需要创建

这个后台代码会被多次使用并可以重复使用,选择写成trait

3.实现分表后的增删改查操作和分表前一样,但默认是对当前月份进行增删改查

trait:

<?php

namespace App\Traits;

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

trait OrderTraits
{
    //是否分表,默认false,即不分表
    protected $isSplitTable = true;

    //原表
    public $originTable;

    //表
    public $endTable;

    /**
     * 后缀参数
     * @var string
     */
    protected $suffix = null;

    /**
     * 年月参数:202104
     * @var string
     */
    public $ym;

    public function init(array $attributes = [], $suffix = null)
    {
        //默认原表
        $this->originTable = $this->table;
        //默认最终表
        $this->endTable = $this->table;

        $this->ym = Carbon::now()->format('Ym');

        //isSplitTable参数为true时进行分表,否则不分表
        if ($this->isSplitTable) {
            //初始化后缀,未传则默认年月分表
            $this->suffix = $suffix ?: $this->ym;
        }
        //初始化分表表名并创建
        $this->setSuffix();
    }

    /**
     * 设置表后缀, 如果设置分表后缀,可在service层调用生成自定义后缀表名,
     * 但每次操作表之前都需要调用该方法以保证数据表的准确性
     * @param $suffix
     */
    public function setSuffix($suffix = null)
    {
        //isSplitTable参数为true时进行分表,否则不分表
        if ($this->isSplitTable) {
            //初始化后缀,未传则默认年月分表
            $this->suffix = $suffix ?: $this->ym;
        }
        if ($this->suffix !== null) {
            //$this->endTable = $this->getTable() . '_' . $suffix;
            $this->endTable = $this->originTable . '_' . $this->suffix;

            //最终表替换模型中声明的表作为分表使用的表
            $this->table = $this->endTable;
        }
        //调用时,创建分表,格式为 table_{$suffix}
        //未传自定义后缀情况下,,默认按年月分表格式为:orders_202205
        //无论使用时是否自定义分表名,都会创建默认的分表,除非关闭该调用
        $this->createTable();
    }

    /**
     * 提供一个静态方法设置表后缀
     * @param string $suffix
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public static function suffix($suffix = null)
    {
        $instance = new static;
        $instance->setSuffix($suffix);
        return $instance->newQuery();
    }

    /**
     * 创建新的"table_{$suffix}"的模型实例并返回
     * @param array $attributes
     * @param bool $exists
     * @return object $model
     */
    public function newInstance($attributes = [], $exists = false)
    {
        $model = parent::newInstance($attributes, $exists);
        $model->setSuffix($this->suffix);
        return $model;
    }

    /**
     * 创建分表,没有则创建,有则不处理
     */
    protected function createTable()
    {
        info("createTable===============", [Schema::hasTable($this->endTable)]);
        //初始化分表,,按年月分表格式为:orders_202205
        if (!Schema::hasTable($this->endTable)) {
            info("创建表==========", [$this->endTable]);
            DB::update("create table {$this->endTable} like {$this->originTable}");
        }
    }

}

在order模型使用trait:(任何模型都可使用这个trait进行按月分表)

    use OrderTraits;

    protected $table = "orders";
    protected $primaryKey = 'id';
    protected $guarded = [];

    protected $columns;

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        // 初始化分表处理
        $this->init();
    }

效果:

按月分表适用场景:

按月分表作为分库分表的策略之一,可以做到冷热数据。

比如,本月的数据一般就是热数据,而之前月份的数据就是冷数据。

但是,应注意一件事情:如果本月写入数据很多,而上个月或者下个月数据写入很少并且整个业务里根本不需要做一些月份数据的统计,就背离了因数据量多而进行分表的出发点,所以,分库分表应结合场景选用较为合适的策略,相比之下,取模适用场景比较广,可以较为均匀分担表数据。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值