热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThinkPHP中的分表使用

提供各种官方和用户发布的代码示例,代码参考,欢迎大家交流学习
讲讲ThinkPHP中的分表使用
数据分表

对于大数据量的应用,经常会对数据进行分表,有些情况是可以利用数据库的分区功能,但并不是所有的数据库或者版本都支持,因此我们可以利用ThinkPHP内置的数据分表功能来实现。帮助我们更方便的进行数据的分表和读取操作。

和数据库分区功能不同,内置的数据分表功能需要根据分表规则手动创建相应的数据表。

在需要分表的模型中定义partition属性即可。

protected $partition = array(
'field' => 'name',// 要分表的字段 通常数据会根据某个字段的值按照规则进行分表
'type' => 'md5',// 分表的规则 包括id year mod md5 函数 和首字母
'expr' => 'name',// 分表辅助表达式 可选 配合不同的分表规则
'num' => 'name',// 分表的数目 可选 实际分表的数量
);
定义好了分表属性后,我们就可以来进行CURD操作了,唯一不同的是,获取当前的数据表不再使用getTableName方法,而是使用getPartitionTableName方法,而且必须传入当前的数据。然后根据数据分析应该实际操作哪个数据表。因此,分表的字段值必须存在于传入的数据中,否则会进行联合查询。

这是tp3.2.3官方文档介绍的,对于还未阅读tp源代码的coder,光看这几句话其实是很难理解如何在tp中使用分表技术的。之前我有专门了解过分表原理,再结合tp的源代码,我和分享一下我是怎么使用tp中的分表。
一、准备工作
1、安装最新的tp3.2.3框架 http://thinkphp1.cn/down/framework.html
2、按自己的喜欢新建测试数据库(例如: thinkphp),接下来建表,因为我只需要完成功能演示就行,因此我就简单地建了tp_user、tp_blog_1、tp_blog_2。表结构如下:
表user:
id: 用户id, 自增,我们blog分表就是根据这个id去定位表的;
username: 账号

表tp_blog_1:
id: 博客id, 自增
uid: 作者用户 id
title: 标题
content: 内容

表tp_blog_2和表tp_blog_1一样
可以发现,我们是对blog表进行了分表操作,表的数量是2。
手动添加一些user表数据,演示要用到。

二、核心部分:建立模型
user表的模型和正常情况一样,这里不作说明。
重点在于blog表的模型,我直接先上BlogModel: namespace Home\Model;
use Think\Model\AdvModel;
class BlogModel extends AdvModel{

protected $tableName = 'blog';
Protected $autoCheckFields = false; //一定要关闭字段缓存,不然会报找不到表的错误

protected $partition = array(
'field' => 'uid',// 要分表的字段 通常数据会根据某个字段的值按照规则进行分表,我们这里按照用户的id进行分表
'type' => 'mod',// 分表的规则 包括id year mod md5 函数 和首字母,此处选择mod(求余)的方式
'expr' => '',// 分表辅助表达式 可选 配合不同的分表规则,这个参数没有深入研究
'num' => '2',// 分表的数目 可选 实际分表的数量,在建表阶段就要确定好数量,后期不能增减表的数量
);

/**
* 计算在哪张表
* @param array $data
* @return \Think\Model
*/
public function computeTable($data = []){
$data = empty($data) ? $_POST : $data;
$table = $this->getPartitionTableName($data);
return $this->table($table);
}
这样我们的分表模型就可以工作了,接下来进行增删改查的演示操作。

三、演示
1、插入数据:
在BlogModel中新增函数addOne:/**
* 添加一条数据
* @param array $data
* @return bool|int
*/
public function addOne($data=[]){
if(empty($data[$this->partition['field']])){
E('缺少' . $this->partition['field']);
}
$data['id'] = intval($this->computeTable()->max('id')) + 1;
if($this->create($data)){
$id = $this->computeTable($data)->add();
if($id === false){
$this->error = '插入数据错误';
return false;
}else{
return $data['id'];
}
}
return false;
}
在Home/Controller/IndexController文件新增操作addBlog:/**
* 新增数据演示
*/
public function addBlog($uid=1){
$blogM = D('Blog');
for($i=1; $i <4; $i++){
$this->show("
添加第{$i}条数据
");
$data = [&#039;title&#039;=>&#039;标题&#039;.$i, &#039;content&#039;=>&#039;内容内容&#039;, &#039;uid&#039;=>$uid];

$result = $blogM->addOne($data);
if($result !== false){
$this->show(&#039;插入数据后的id为:&#039;.$result);
}else{
$this->show(&#039;插入数据失败,失败原因:&#039;.$blogM->getError());
}
}

}
打开浏览器访问: 域名/index.php?s=/home/index/addBlog/uid/1 ,可以自行核对是否达到预期的效果。

2、获取所有博客:
在BlogModel中新增函数getAll:/**
* 获取所有记录
*/
public function getAll(){

return $this->computeTable()->select();
}
在Home/Controller/IndexController文件新增操作getBlogs:/**
* 获取所有数据演示
*/
public function getBlogs(){
$blogM = D(&#039;Blog&#039;);
$list = $blogM->getAll();
dump($list);
}
浏览器访问: 域名/index.php?s=/home/index/getBlogs,可以自行核对是否达到预期的效果。

3、根据条件获取多条数据
在BlogModel中新增函数getList:/**
* 条件查询列表
* @param $map
* @return mixed
*/
public function getList($map){
if(empty($map[$this->partition[&#039;field&#039;]])){
E(&#039;缺少&#039; . $this->partition[&#039;field&#039;]);
}

return $this->computeTable($map)->where($map)->select();
}
在Home/Controller/IndexController文件新增操作getBlogByUid:/**
* 根据条件查询数据演示
* @param int $uid
*/
public function getBlogsByUid($uid = 1){
$blogM = D(&#039;Blog&#039;);
$list = $blogM->getList([&#039;uid&#039; => $uid]);
dump($list);
}
浏览器访问: 域名/index.php?s=/home/index/getBlogsByUid/uid/1,可以自行核对是否达到预期的效果。

4、查询单条记录
在BlogModel中新增函数getOne:/**
* 根据查询条件获取一条记录
* @param $map
* @return mixed
*/
public function getOne($map){
if(empty($map[$this->partition[&#039;field&#039;]])){
E(&#039;缺少&#039; . $this->partition[&#039;field&#039;]);
}
return $this->computeTable($map)->where($map)->find();
}
在Home/Controller/IndexController文件新增操作blogDetail:/**
* 查询一条数据演示
* @param int $uid
* @param int $blog_id
*/
public function blogDetail($uid = 1, $blog_id=1){
$blogM = D(&#039;Blog&#039;);
$data = $blogM->getOne([&#039;uid&#039; => $uid, &#039;id&#039; => $blog_id]);
dump($data);
}
浏览器访问: 域名/index.php?s=/home/index/blogdetail/uid/1/blog_id/1,可以自行核对是否达到预期的效果。

5、更新一条记录
在BlogModel中新增函数updateOne:/**
* 更新一条记录
* @param $map
* @param $data
* @return bool
*/
public function updateOne($map, $data){
if(empty($map[$this->partition[&#039;field&#039;]])){
E(&#039;缺少&#039; . $this->partition[&#039;field&#039;]);
}
if($this->create($data)){
$res = $this->computeTable($map)->save($data);
if($res === false){
$this->error = &#039;更新数据出错&#039;;
}else{
return $res; //更新的数据条数
}
}
return false;
}
在Home/Controller/IndexController文件新增操作updateBlog:/**
* 更新一条记录演示
* @param int $uid
* @param int $blog_id
*/
public function updateBlog($uid=1, $blog_id=1){
$blogM = D(&#039;Blog&#039;);
$map = [&#039;uid&#039;=>$uid, &#039;id&#039;=>$blog_id];
$this->show("id为".$blog_id."的博客在修改之前为
");
$blog = $blogM->getOne($map);
dump($blog);

$this->show("id为".$blog_id."的博客在修改之后为
");
$data = [&#039;title&#039; => &#039;我被修改了&#039;, &#039;id&#039; => $blog_id];
$res = $blogM->updateOne([&#039;uid&#039; => $uid], $data);
if($res === false){
dump($blogM->getError());
}else{
$blog = $blogM->getOne($map);
dump($blog);
}
}
浏览器访问: 域名/index.php?s=/home/index/updateblog/uid/1/blog_id/1,可以自行核对是否达到预期的效果。

6、删除一条数据
在BlogModel中新增函数delOne:/**
* 删除一条记录
* @param $map
* @return bool|mixed
*/
public function delOne($map){
if(empty($map[$this->partition[&#039;field&#039;]])){
E(&#039;缺少&#039; . $this->partition[&#039;field&#039;]);
}
$res = $this->computeTable($map)->where($map)->delete();
if($res === false){
$this->error = &#039;删除数据出错&#039;;
return false;
}else{
return $res; //删除数据个数
}
}
在Home/Controller/IndexController文件新增操作delBlog:/**
* 删除一条数据演示
* @param int $uid
* @param int $blog_id
*/
public function delBlog($uid = 1, $blog_id=1){
$blogM = D(&#039;Blog&#039;);
$map = [&#039;uid&#039; => $uid, &#039;id&#039; => $blog_id];
$this->show("准备要删除的博客
");
dump($blogM->getOne($map));

$this->show("删除结果
");
$res = $blogM->delOne($map);
dump($res);
}
浏览器访问: 域名/index.php?s=/home/index/delblog/uid/1/blog_id/1,可以自行核对是否达到预期的效果。

以上只例举了一些其他操作,其他tp模型具有的操作可以举一反三得到,希望各自去使用。

AD:真正免费,域名+虚机+企业邮箱=0元

推荐阅读
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • Lodop中特殊符号打印设计和预览样式不同的问题解析
    本文主要解析了在Lodop中使用特殊符号打印设计和预览样式不同的问题。由于调用的本机ie引擎版本可能不同,导致在不同浏览器下样式解析不同。同时,未指定文字字体和样式设置也会导致打印设计和预览的差异。文章提出了通过指定具体字体和样式来解决问题的方法,并强调了以打印预览和虚拟打印机测试为准。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Final关键字的含义及用法详解
    本文详细介绍了Java中final关键字的含义和用法。final关键字可以修饰非抽象类、非抽象类成员方法和变量。final类不能被继承,final类中的方法默认是final的。final方法不能被子类的方法覆盖,但可以被继承。final成员变量表示常量,只能被赋值一次,赋值后值不再改变。文章还讨论了final类和final方法的应用场景,以及使用final方法的两个原因:锁定方法防止修改和提高执行效率。 ... [详细]
  • 本文介绍了求解gcdexgcd斐蜀定理的迭代法和递归法,并解释了exgcd的概念和应用。exgcd是指对于不完全为0的非负整数a和b,gcd(a,b)表示a和b的最大公约数,必然存在整数对x和y,使得gcd(a,b)=ax+by。此外,本文还给出了相应的代码示例。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 电销机器人作为一种人工智能技术载体,可以帮助企业提升电销效率并节省人工成本。然而,电销机器人市场缺乏统一的市场准入标准,产品品质良莠不齐。创业者在代理或购买电销机器人时应注意谨防用录音冒充真人语音通话以及宣传技术与实际效果不符的情况。选择电销机器人时需要考察公司资质和产品品质,尤其要关注语音识别率。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
author-avatar
朱美萍客户
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有