如何在网站发广告,新建网站后域名跳转到别的网站了,哪里有学网页设计,网线制作过程简述前言
先交代下背景,在一个项目中,有一个数据表有水平分表的需求。当时想找到一种方法#xff0c;把对数据库的操作#xff0c;写到一个模型里#xff0c;通过去换模型属性中的table来达到代码不变操作的数据表变化的效果。 我们都知道#xff0c;模型要想关联数据表的话把对数据库的操作写到一个模型里通过去换模型属性中的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(fieldusername,typeid,num4);public function getDao($dataarray()) {$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($dataarray()) {// 对数据表进行分区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($i0;$i$this-partition[num];$i)$tableName[] SELECT * FROM .$this-getTableName()._.$i;$tableName ( .implode( UNION ,$tableName).) AS .$this-name;return $tableName;}}温馨提示 其中 partition 方法指定要查询的分表where 方法则是查询条件。 需要注意的是分表可能会给应用带来更高的维护成本和查询复杂度需要在实际开发中根据业务需要进行选择 复杂模型实现不了的业务逻辑只能用原生sql 来实现。团队封装的模型基本够用大数据项目也不会用轻量级框架有更好的分表查询方法可以欢迎留言。用到那、学到哪
其他文档
ThinkPHP中的分表使用