IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 9.laravel 简单尝试分表 -> 正文阅读

[PHP知识库]9.laravel 简单尝试分表

项目中日志表数据量大一般会做分表的处理。

思路

1.基础表:orders
里面包含所有字段的类型
2.分表,按照后缀分表,例:orders_202112
但是这些表肯定是后台代码创建而不是人为创建的。
表创建的时候肯定的先判断表是否存在,不存在则创建。
这个判断肯定会使用多次,需要写一个trait
例:
3.就是单表或者多表的插入跟查询了

设计

1.Trait

这个是我从网上粘了一个。我感觉设计思路还挺好的。
主要就是判断表是否存在不存在就创建

<?php

namespace App\Traits;

use App\Exceptions\ResponseApiException;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

trait SplitTableTrait
{
    //是否分表,默认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}
        //未传自定义后缀情况下,,默认按年月分表格式为:b_log_202101
        //无论使用时是否自定义分表名,都会创建默认的分表,除非关闭该调用
        $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
     */
    // 创建新的"chapters_{$suffix}"的模型实例并返回
    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)]);
        //初始化分表,,按年月分表格式为:b_log_202101
        if (!Schema::hasTable($this->endTable)) {
            info("创建表==========", [$this->endTable]);
            DB::update("create table {$this->endTable} like {$this->originTable}");
        }
    }

    /**
     * 排序字段
     * @var
     */
    protected $orderByField = null;

    /**
     * 排序类型,asc:正序,desc:倒序,默认倒序
     * @var
     */
    protected $orderBy = 'desc';

    /**
     * 执行union all对分表的最终扥分页查询
     * @param $queries
     * @return array
     */
    public function dealListByUnionAllQuery($queries, $limit= 10)
    {
        //弹出一张表作为union的开始
        $unionQuery = $queries->shift();
        //循环剩下的表添加union
        $queries->each(function ($item, $key) use ($unionQuery) {
            $unionQuery->unionAll($item);
        });
        //设置临时表的名称,添加临时表,顺序不能反过来,否则用关联约束会找不到表
        $endQuery =
            DB::table(DB::raw("({$unionQuery->toSql()}) as union_" . $this->originTable))
                //合并查询条件
                ->mergeBindings($unionQuery);
        if ($this->orderByField) {
            $endQuery->orderBy($this->orderByField, $this->orderBy);
        }
        $lists = $endQuery
            //分页
            ->paginate($limit)
            ->toArray();
        //处理分页数据
//        $list = dealPaginate($lists);
        return $lists;
    }
}

2.model使用

  • 使用trait: use SplitTableTrait;
  • 构造方法里面初始化
<?php
namespace App\Models;

use App\Traits\SplitTableTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

class Orders extends Model
{
    use SplitTableTrait;
    
    // 表名
    protected $table = "orders";
    // 主键
    protected $primaryKey = 'id';

    protected $columns; // 未知

    protected $fillable = ['name'];

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        info("Orders==========构造方法");
        // 初始化分表处理
        $this->init();

//        // 初始化表字段
//        $table_columns = DB::select('show columns from '.$this->table);
//        $this->columns = array_column($table_columns, 'Field');
//        $this->fillable = array_values($this->columns);
    }
}

3.单表查询

 // 普通查询
 $order = new Orders();
 $order->setTable('orders_'. $prefix );
 $res = $order->get();
 dd($res);

 // model查询
 $order = Orders::suffix($prefix);
 $res = $order->get()->pluck("name");
 dd($res);

 // 普通保存可以
 $order = new Orders();
 $order->setTable('orders_'. $prefix );
 $order->name = "333333";
 $order->save();

 // model保存可以
 $order = Orders::suffix($prefix);
 $res = $order->firstOrCreate(["name" => "wwwwww"]);
 
 // 普通更新
 $order = new Orders();
 $order->setTable('orders_'. $prefix );
 $order_desc = $order->where("id" , 1)->first();
 $order_desc->name= "hshshs";
 $order_desc->save();
 $res = $order->update( [
     "name" => "heshuo"
   ]);
 dd($res);
 
 // model更新
 $order = Orders::suffix($prefix);
 $res = $order->updateOrCreate( [
     "id" => 1
 ],[
     "name" => "heshuo111"
   ]);
 dd($res);

4.连表查询

$query = new Orders();
// 查询集合
$queries = collect();
// 循环比较年月,添加每一张表的查询
$startTime = Carbon::parse('-1 months')->firstOfMonth()->toDateTimeString();
$endTime = Carbon::now()->toDateTimeString();
$start = Carbon::parse($startTime);
$end = Carbon::parse($endTime);

$fields = [];
for ($i = $start->copy(); $i->format('Ym') <= $end->format('Ym'); $i->addMonth()) {
    //根据是否分表,确定查询真正表
    $curTable = "{$query->originTable}_{$i->format('Ym')}";
    //如果表不存在则跳过本次循环
    if (!Schema::hasTable($curTable)) {
        continue;
    }
    $queries->push(
        DB::table($curTable)
            // 建议都用select查询字段,SQL尽可能的优化性能
            ->where('created_at', '>=', $startTime)
            ->where('created_at', '<=', $endTime)
            ->when($fields, function ($query) use ($fields) {
                info("-----走when了", []);
                $query->select($fields);
            })
    );
}
$res = $query->dealListByUnionAllQuery($queries);
dd($res);
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-12-08 13:37:21  更:2021-12-08 13:37:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/14 14:38:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码