Laravel分表联合查询

分表的好处:

分表是将单个数据库表拆分为多个较小的表的过程。这样做有以下几个潜在的好处:

1. 提升查询性能:当表中包含大量数据时,查询可能变得缓慢。通过分表,可以将数据分散到多个表中,每个表的数据量较小,从而提高查询性能。

2. 管理数据更灵活:通过分表,可以将数据按照某种规则(例如时间、地理位置等)进行分隔和存储。这样可以更容易地管理和维护数据,例如删除过期数据或备份数据。

3. 分布式存储:分表为分布式存储提供了基础。可以将不同的表存储在不同的服务器上,以实现数据的水平扩展和负载均衡。

4. 降低锁冲突:在高并发环境中,如果多个查询操作同时访问同一个表,可能会导致锁冲突和性能问题。通过分表,可以将查询操作分散到多个表上,减少锁冲突的可能性,提高并发性能。

5. 数据隔离:在某些情况下,你可能希望将数据进行隔离,以便不同的用户或不同的业务操作可以在独立的表中进行。分表可以提供更好的数据隔离和安全性。

需要注意的是,分表也会带来一些挑战和额外的复杂性。例如,需要根据分表规则调整查询逻辑,处理表之间的关联关系以及维护分表结构的一致性。因此,在决定使用分表时,需要综合考虑应用程序的需求、数据量和性能需求,并仔细规划和实施分表策略。

以下提供的Demo案例:

以产品表exa_product_0、exa_product_1、exa_product_2、exa_product_3四个表为例:

CREATE TABLE `exa_product` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `category_id` tinyint DEFAULT '0' COMMENT '分类ID',
  `goods_name` varchar(150) DEFAULT '' COMMENT '产品名称',
  `created_at` int DEFAULT NULL,
  `updated_at` int DEFAULT NULL,
  `deleted_at` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3

1、定义基础模型类:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use DateTimeInterface;
use Illuminate\Support\Facades\Schema;

class Base extends Model
{

    use SoftDeletes;

    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';
    const DELETED_AT = 'deleted_at';

    /**
     * @var string 表后缀
     */
    protected $suffix = '';

    /**
     * @var string[] 隐藏输出字段
     */
    protected $hidden = ['deleted_at'];

    /**
     * 返回格式化时间
     *
     * @param DateTimeInterface $date
     * @return string
     */
    protected function serializeDate(DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }

    /**
     * 设置动态表名
     *
     * @param string $suffix
     * @return Base
     */
    public function scopeSuffix(string $suffix)
    {
        return $this->setTable($this->getTableWithSuffix($suffix));
    }

    /**¬
     * 根据传递的表后缀名,获取完整的表名
     *
     * @param string $suffix 表后缀名
     * @return string 完整的表名
     */
    private function getTableWithSuffix(string $suffix): string
    {
        $table = $this->getTable() . $suffix;
        if(!Schema::hasTable($table)) {
            throw new \InvalidArgumentException("Table [{$table}] not found.");
        }
        return $table;
    }
}

二、定义产品模型类:

<?php

namespace App\Models\Goods;

use App\Models\Base;

class ProductModel extends Base
{
    /**
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * @var int 分表数量
     */
    public const TABLE_COUNT = 4;
}

三、查询分页列表:

<?php

namespace App\Trans\Goods;

use App\Models\Goods\ProductModel;
use Illuminate\Support\Facades\DB;

class ProductTrans
{
    /**
     * 产品列表
     * @param $params
     * @return array|int
     */
    public static function getProductList($params = [])
    {
        $options = [
            'categoryId' => 0,
            'goodsName'  => '',
            'fields'     => ['*'],
            'orderByStr' => 'category_id-desc',
            'page'       => 1,
            'pageSize'   => 10,
            'isGetCount' => false
        ];

        if($params && is_array($params)) {
            $options = array_merge($options, $params);
        }
        extract($options);

        // 查询集合
        $queries = collect();
        for ($i = 0; $i < ProductModel::TABLE_COUNT; $i++) {
            $query = DB::table('product_' . $i)->select($fields);
            if($categoryId) {
                $query = $query->where('category_id', $categoryId);
            }
            if($goodsName) {
                $query = $query->where('goods_name', 'like', '%' . $goodsName . '%');
            }
            $queries->push($query);
        }

        // 取出第一个作为查询对象,其他的作为合并对象
        $unionQuery = $queries->shift();

        // 循环剩下的表添加union
        $queries->each(function($item) use ($unionQuery) {
            $unionQuery->unionAll($item);
        });

        $endQuery = DB::table(DB::raw("({$unionQuery->toSql()}) as product"))->mergeBindings($unionQuery);

        // 总条数
        $count = $endQuery->count();
        if($isGetCount) {
            return $count;
        }

        // 排序
        foreach (formatOrderby(['orderByStr' => $orderByStr]) as $val) {
            $endQuery = $endQuery->orderBy($val[0], $val[1]);
        }

        $list = $endQuery->skip(($page - 1) * $pageSize)->take($pageSize)->get()->toArray();

        return camel(['list' => objectToArray($list), 'total' => $count]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值