thinkphp5水平分割表partition,以及查询操作
前言
先交代下背景,在一个项目中,有一个数据表有水平分表的需求。当时想找到一种方法,把对数据库的操作,写到一个模型里,通过去换模型属性中的table来达到代码不变操作的数据表变化的效果。
我们都知道,模型要想关联数据表的话,有两中方式,第一种就是将模型名和数据表一致。这样模型就会默认关联到名字对应的数据表。第二种就是定义模型的 protected $table 来指定表明。
添加链接描述
模型初始化
ThinkPHP5内置了partition方法,可用于实现简单的分表。新增,修改,删除,查询单条数据时,用parition方法都可以轻松搞定,因为这些操作有一个共同的特点,就是能事先明确的知道,我要操作的是哪一条记录。但有一个需求,ThinkPHP5似乎没有解决,比如当一个大表,被拆分成若干个子表时,如何根据相关条件及排序获取分页数据。这种需求场景下,由于事先并不知道哪些数据会出现在第一页,哪些数据会出现在第二页,这些根据检索条件动态匹配的列表数据,该如何查询呢?
模型层
<?php
namespace app\common\model;
use think\Model;
class WalletLog extends Model
{protected $table = 'tb_walletlog';protected $pk = 'walletid';private function getRule(){return ['type' => 'mod', // 分表方式'num' => 3 // 分表数量];}public function saveData($data, $user_id){return $this->partition(['user_id' => $user_id], "user_id", $this->getRule())->insert($data);}public function getAll($where, $field = "*", $user_id){return $this->partition(['user_id' => $user_id], "user_id", $this->getRule())->where($where)->field($field)->select();}//查询所有分割表public function getAll2(){return $this->partition('', '', $this->getRule())->select();}
}
分库分表查询分表与其他表关联查询 join 不好使用(各种sql 报错)估计不支持
解决方案:
插入使用分表操作,进行分割数据,查询使用普通联合/聚合查询
1、模型层调整 查询
namespace application\workflow\model;
use think\Model;
class Init_Model extends Model
{protected $pk = 'id';//初始化表名public function __construct($name = ''){if (!empty($name)) {$this->name = $name;}}
}
使用时:$model = new init_model(‘test’); //成功改变了数据表
$model->get(); //操作时二次走__construct成空白,还原成没有表名;
请问有内置方法动态改变表名吗,对于动态管理的东东很须要这个功能呀
前人栽树,后人挖坑,哎
2、 执行sql 查询(拼接表名称来实现查询)
select count(1) as total from .$tables['countSql']
3、Db模型函数查询
注意:不要使用任何 SQL 语句中会出现的关键字当表名、字段名,例如 order 等。会导致数据模型拼装 SQL 语句语法错误。
thinkphp5 看云文档 partition 方法用于是数据库水平分表
partition 方法用法如下:
// 用于写入
$data = ['user_id' => 110,'user_name' => 'think'
];$rule = ['type' => 'mod', // 分表方式'num' => 10 // 分表数量
];
Db::name('log')->partition(['user_id' => 110], "user_id", $rule)->insert($data);// 用于查询
Db::name('log')->partition(['user_id' => 110], "user_id", $rule)->where(['user_id' => 110])->select();
4、闭包用法:
每个union方法相当于一个独立的SELECT语句。MySQL通过创建并填充临时表的方式来执行union查询。除非确实要消除重复的行,否则建议使用union all。原因在于如果没有all这个关键词,MySQL会给临时表加上distinct选项,这会导致对整个临时表的数据做唯一性校验,这样做的消耗相当高。
Db::field('name')->table('think_user_0')->union('SELECT name FROM think_user_1')->union('SELECT name FROM think_user_2')->select();
//或者下面这种用法
Db::field('name')->table('think_user_0')->union(['SELECT name FROM think_user_1','SELECT name FROM think_user_2'])->select();
//支持UNION ALL 操作,例如:
Db::field('name')->table('think_user_0')->union(['SELECT name FROM think_user_1','SELECT name FROM think_user_2'],true)->select();
其他案例
应用ThinkPHP内置的分表算法处理百万级用户数据.(适合流水类记录表)
数据表:house_member_0house_member_1house_member_2house_member_3模型中//class MemberModel extends AdvModel {protected $partition = array('field'=>'username','type'=>'id','num'=>'4');public function getDao($data=array()) {$data = empty($data) ? $_POST : $data;$table = $this->getPartitionTableName($data);return $this->table($table);}}方法中class MemberAction extends BaseAction {public function login() {if($this->isPost()) {$this->validToken();$dao = D('Member')->getDao();$res = $dao->where('username = '.$_POST['username'])->find();// output 为自定义方法// $isAjax - bool$this->output(false);}$this->display();}}/**+----------------------------------------------------------* 得到分表的的数据表名+----------------------------------------------------------* @access public+----------------------------------------------------------* @param array $data 操作的数据+----------------------------------------------------------* @return string+----------------------------------------------------------*/public function getPartitionTableName($data=array()) {// 对数据表进行分区if(isset($data[$this->partition['field']])) {$field = $data[$this->partition['field']];switch($this->partition['type']) {case 'id':// 按照id范围分表$step = $this->partition['expr'];$seq = floor($field / $step)+1;break;case 'year':// 按照年份分表if(!is_numeric($field)) {$field = strtotime($field);}$seq = date('Y',$field)-$this->partition['expr']+1;break;case 'mod':// 按照id的模数分表$seq = ($field % $this->partition['num'])+1;break;case 'md5':// 按照md5的序列分表$seq = (ord(substr(md5($field),0,1)) % $this->partition['num'])+1;break;default :if(function_exists($this->partition['type'])) {// 支持指定函数哈希$fun = $this->partition['type'];$seq = (ord(substr($fun($field),0,1)) % $this->partition['num'])+1;}else{// 按照字段的首字母的值分表$seq = (ord($field{0}) % $this->partition['num'])+1;}}return $this->getTableName().'_'.$seq;}else{// 当设置的分表字段不在查询条件或者数据中//进行联合查询,必须设定 partition['num']$tableName = array();for($i=0;$i<$this->partition['num'];$i++)$tableName[] = 'SELECT * FROM '.$this->getTableName().'_'.$i;$tableName = '( '.implode(" UNION ",$tableName).') AS '.$this->name;return $tableName;}}
温馨提示:
其中 partition 方法指定要查询的分表,where 方法则是查询条件。
需要注意的是,分表可能会给应用带来更高的维护成本和查询复杂度,需要在实际开发中根据业务需要进行选择
复杂模型实现不了的业务逻辑只能用原生sql 来实现。(团队封装的模型基本够用,大数据项目也不会用轻量级框架)有更好的分表查询方法可以欢迎留言。用到那、学到哪!!!
其他文档
ThinkPHP中的分表使用
相关文章:
thinkphp5水平分割表partition,以及查询操作
前言 先交代下背景,在一个项目中,有一个数据表有水平分表的需求。当时想找到一种方法,把对数据库的操作,写到一个模型里,通过去换模型属性中的table来达到代码不变操作的数据表变化的效果。 我们都知道,模型要想关联数据表的话&a…...
docker部署aria2-pro
前言 我平时有一些下载视频和一些资源文件的需求,有时候需要离线下载,也要速度比较快的方式 之前我是用家里的玩客云绝育之后不再写盘当下载机用的,但是限制很多 我发现了aria2 这个下载器非常适合我,而有个大佬又在原来的基础…...
vue中Mixins
使用 Mixins 的主要优点包括: 代码复用: 可以将常用的逻辑封装在 Mixin 中,然后在多个组件中重复使用。逻辑分离: 将不同功能的代码分开管理,使代码更加清晰和易于维护。灵活性: Mixins 允许你在组件中引入多个 Mixin,并且可以根…...
linux常用指令(定期更新)
linux常用指令 1.页相关页大小 2.系统参数3.启动参数4.网络参数查询网卡所属numa节点信息网络测速相关iperf测试sar监控网卡流量查看网卡txqueuelen和mtu抓包tcpdump 网络数据收发状态snmp协议栈netstat -i所有网口TX-OK、RX-OKnetstat-s查看各个协议的收发数据ethtool -S单个网…...
【项目】图书管理系统
目录 前言: 项目要求: 知识储备: 代码实现: Main: Books包: Book: BookList: Operate包: Operate: addOperate: deleteOperate: exitOperate: findOperate:…...
华为OD机试 - 疫情扩散时间计算 - 矩阵(Java 2024 C卷 200分)
目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷&am…...
[数据集][图像分类]棉花叶子病害分类数据集2293张4类别
数据集类型:图像分类用,不可用于目标检测无标注文件 数据集格式:仅仅包含jpg图片,每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数):2293 分类类别数:4 类别名称:["diseased_cotton_leaf"…...
《辐射4》是一款什么样的游戏 怎样在mac电脑上玩到《辐射4》辐射4攻略 辐射4开局加点 怎么在Mac电脑玩Steam游戏
辐射4(Fallout 4)是由Bethesda开发的一款动作角色扮演类游戏,为《辐射》系列游戏作品的第四代,于2015年11月10日发行。游戏叙述了主角一家在核爆当天(2077年10月23日),被Vault-Tec(避…...
视频推拉流EasyDSS平台直播通道重连无法转推的原因排查与解决
视频推拉流EasyDSS视频直播点播平台,集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 用户使用EasyDSS平台对直播通道进行转推,发现只要关闭…...
Javaweb之SpringBootWeb案例之自动配置案例的自定义starter测试的详细解析
3.2.4.3 自定义starter测试 阿里云OSS的starter我们刚才已经定义好了,接下来我们就来做一个测试。 今天的课程资料当中,提供了一个自定义starter的测试工程。我们直接打开文件夹,里面有一个测试工程。测试工程就是springboot-autoconfigurat…...
java包的相关概念
包:有效地管理类的一个机制。 包名的目的:通过隶属不同的包有效的区分不同源文件中名字相同的类 包语句 声明:通过关键字 package声明包语句。 位置:源文件中的第一条语句。 作用:为该源文件中声明的类指定包名。 …...
window搭建本地mongo数据库并导入数据
1 window下载mongo数据库 官网:www.mongodb.com 选择 Products > Community Edition 就能进入社区版 在这里下载 windows 版对应的安装包 注意:6.0.1 版本的 MongoDB 配置环境变量有问题,并且我不知道怎么解决,如果想要避免出…...
如何为Android车载应用开发通知?
如何为Android车载应用开发通知?在开发车载应用的通知时,开发者需要考虑到驾驶安全,确保通知不会分散驾驶员的注意力。这通常意味着通知应该是非侵入性的,或者在不影响驾驶的情况下提供信息。开发者可以使用Android的通知API来创建…...
centos上部署k8s
环境准备 四台Linux服务器 主机名 IP 角色 k8s-master-94 192.168.0.94 master k8s-node1-95 192.168.0.95 node1 k8s-node2-96 192.168.0.96 node2 habor 192.168.0.77 镜像仓库 三台机器均执行以下命令: 查看centos版本 [rootlocalhost Work]# cat /…...
网络安全: Kali Linux 进行 MSFvenom 程序利用
目录 一、实验 1.环境 2. Kali Linux 进行 MSFvenom 程序利用 3. 创建计划任务自动运行 MSFvenom 程序 二、问题 1.在线加密解密 2.MSF 运行失败 3.MobaXterm 连接Ubuntu 失败 一、实验 1.环境 (1)主机 表1 主机 系统版本IP备注Kali Linux20…...
浅显易懂C语言指针!!!(三)
文章目录 Pointers as function arguments - call by reference//函数传值vs传引用 Pointers as function arguments - call by reference//函数传值vs传引用 #include<stdio.h> void Increment(int a){//increment 增加 a a 1;//;函数中的是形式参数 形参…...
01 LM 算法及 Cpp 实现
文章目录 01 LM 算法及 Cpp 实现1.1 应用1.2 阻尼法推导1.3 Cpp 算法实现 01 LM 算法及 Cpp 实现 1.1 应用 LM 算法用于解决非线性最小二乘问题 min x F ( x ) 1 2 ∥ f ( x ) ∥ 2 2 (1) \min _x F(x)\frac{1}{2}\|f(\boldsymbol{x})\|_2^2 \tag{1} xminF(x)21∥f(x…...
【网络安全架构】互联网正对中国社会、经济、文化等各个领域产生巨大影响‘
摘 要: 中国互联网近年来飞速发展,普及率达到38.4%。已稳居世界第一网民大国的地位。互联网正对社会、经济、文化等各个领域产生巨大影响。2011年12月21日“泄密门”事件,再次敲响网络安全的警钟。网络攻击和入侵都是根据网络模型不同层次的特…...
【笔记】Android ServiceStateTracker 网络状态变化逻辑及SPN更新影响
业务简介 在网络状态变化的时候(数据或WiFi),会更新SPN。 基于Android U的代码分析。 分类:SPN Data_Dic-的博客-CSDN博客 功能逻辑 状态说明 飞行模式下注册上WFC的话,注册状态MD上报 regState: NOT_REG_MT_NOT…...
2PC和3PC的区别是什么
2PC提交协议是什么 二阶段提交是指,在计算机网络一级数据库领域内,为了使基于分布式系统的架构下的所有节点在进行事务提交时保持一致性而设计的一种算法。在分布式系统中,每个节点虽然可以知晓自己操作的成功和失败,但是无法知道…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...
