当单表达到几千万时,查询一次要很久,如果有联合查询,有可能会死在那
分库分表主要就是解决这个问题,减小数据库的负担,缩短查询时间分库
1)按功能分
用户类库、商品类库、订单类库、日志类、统计类库...

2)按地区分
每个城市或省市一个同样的库,加上后缀或前缀如:db_click_bj、db_click_sh...分表1、横向分表 解决表记录太大问题
1)按某个字段分,
比如:discuz的附件表分成10个附件分表pre_forum_attachment_0到pre_forum_attachment_9,还有1个附件索引表pre_forum_attachment存储tid和附件id关系。根据主题的tid最后一位来决定附件要保存在哪个分表。

2)按日期分表
一些日志、统计类的可以按年、月、日、周分表
如:点击量统计click_201901、click_201902

3)使用mysql的merge
先把分表创建好,然后创建总表指定engine= MERGE UNION=(table1,table2) INSERT_METHOD = LAST;

2、纵向分表 解决列过多问题
1)经常组合查询的列放在一个表,常用字段的表可考虑Memory引擎
2)不经常使用的字段单独成表
3)把text、blob等大字段拆分放在附表

如:文章表分成主表news和从表news_data,主表存标题、关键字、浏览量等,从表存具体内容、模板等。

还有很多主流mvc框架都提供了切换数据库访问方法的配置,比如laravel,thinkphp,这里可以去查看各自的框架数据库的配置文件,不在这里介绍。

很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,希望能够去帮助到小伙伴们,可以加入一下我创建的圈子【PHP架构师圈子】,里面有我分享的小白进阶到架构师学习资料以及路线

PHP架构师圈子 - 知乎​www.zhihu.com

用PHP例子实现分库分表操作

用两台机子简单以同个业务库分库,同个表分表,演示插入、查询如何定位库和表并最终成功执行

两台机子:

server1:192.168.1.198

server2:192.168.1.199

两台机子都执行下面操作

1、先创建10个数据库,每个数据库10个表

当然也可以改成百库百表,也可手动创建,我为了方便写了个脚本批量创建

create.php (代码可滑动查看)

<?php
ini_set('memory_limit', '-1');
$con=mysql_connect("192.168.1.198","open","123456");
if($con){    for($i=0;$i<10;$i++){//10个库$sql="drop database cloude_{$i};";//删库 谨慎mysql_query($sql);$sql="create database cloude_{$i} default character set utf8 collate utf8_general_ci;";$do=mysql_query($sql,$con)or die(mysql_error());if($do){mysql_select_db("cloude_{$i}",$con);mysql_query("set name gtf8");for($j=0;$j<10;$j++){        //10个表$sql="drop table if exists user_{$j};";mysql_query($sql);$sql="create table user_{$j}(id char(36) not null primary key,name char(15) not null default '',password char(32) not null default '',sex char(1) not null default '男')engine=InnoDB;";$do=mysql_query($sql,$con) or die(mysql_error());if($do){//echo "create table user_{$j} successful! <br/>";}else{//echo "create error!";}}}}
}else{echo "connect error!!!!";
}

2、分库分表路由实现

Config.php (代码可滑动查看)

<?php
class Config{  public $dsn;  public $user;  public $password;  public $dbname; //分库分表后得到的数据库名public $table; //分库分表后得到的表名private static $config;//mysql配置数组private static $configFile = 'mysql.php'; //配置文件路径 public function __construct($dbname, $table, $id = 0){  if (is_null(static::$config)) {  $config = include(static::$configFile);  static::$config = $config;  }  $config = static::$config;  if (isset($config['shared']) && isset($config['shared'][$dbname])) {  $dbconfig = $config['shared'][$dbname];  $id = is_numeric($id) ? (int)$id : crc32($id);  $database_id = ($id / $dbconfig['database_split'][0]) % $dbconfig['database_split'][1];  $table_id = ($id / $dbconfig['table_split'][0]) % $dbconfig['table_split'][1];  foreach ($dbconfig['host'] as $key => $conf) {  list($from, $to) = explode('-', $key);  if ($from <= $database_id && $database_id <= $to) {  $the_config = $conf;  }  }  $this->dbname = $dbname . '_' . $database_id;  $this->table = $table . '_' . $table_id;  } else {  $this->dbname = $dbname;  $this->table = $table;  $the_config = $config['db'][$dbname];  }  $c = $the_config;  if (isset($c['unix_socket']) && $c['unix_socket']) {  $this->dsn = sprintf('mysql:dbname=%s;unix_socket=%s', $this->dbname, $c['unix_socket']);  } else {  $this->dsn = sprintf('mysql:dbname=%s;host=%s;port=%s', $this->dbname, $c['host'], $c['port']);  }  $this->user = $c['user'];  $this->password = $c['password'];  }  }

3、数据库配置文件mysql.php (代码可滑动查看)

<?php
$default = array(  'unix_socket' => null,  'host' => '192.168.1.198',  'port' => '3306',  'user' => 'open',  'password' => '123456',
);
$db_199 = array(  'unix_socket' => null,  'host' => '192.168.1.199',  'port' => '3306',  'user' => 'open',  'password' => '123456',
);
$config = array(  // 不进行分库分表的数据库  'db' => array(  'hadoop' => $default,  ),  // 分库分表  'shared' => array(  'cloude' => array(  'host' => array(  /** * 编号为 0 到 4 的库使用的链接配置 */ '0-4' => $default,  /** * 编号为 5 到 9 的库使用的链接配置 */ '5-9' => $db_199,   ),  // 分库分表规则  /** * 下面的配置对应10库10表* 如果根据 uid 进行分表,假设 uid 为 224,对应的库表为: *  (224 / 1) % 10 = 4 为编号为 4 的库 *  (224 / 10) % 10 = 1 为编号为 2 的表 */ 'database_split' => array(1, 10),  'table_split' => array(10, 10),  ),  ),
);
return $config;

4、模型类操作数据库

Model.php (代码可滑动查看)

<?php
require_once 'Config.php';//引入配置信息
class Model{  public $config;        //数据库配置public $connection;    //pdoprotected $dbnamePrefix; //库前缀如cloude_50 前缀为cloude protected $tablePrefix;  //表前缀protected $dbname;    //分库分表后对应的库protected $table;     //分库分表后对应的库表public function __construct($id){  $this->config = new Config($this->dbnamePrefix, $this->tablePrefix, $id);                     //根据id找到对应库和表$this->connection = new Pdo($this->config->dsn, $this->config->user, $this->config->password);//实例化pdo  $this->connection->exec("set names utf8");   $this->dbname = $this->config->dbname;$this->table = $this->config->table;  }  public function update(array $data, array $where = array()){  }  public function select(array $condition){ $sqlwhere='';if(!empty($condition)){   foreach ($condition as $field => $value) {  $where[] = '`'.$field.'`='."'".addslashes($value)."'";  }  $sqlwhere .= ' '.implode(' and ', $where);   }$sql="select * from ".$this->dbname.'.'.$this->table;if($sqlwhere){$sql.=" where $sqlwhere";}$res=$this->connection->query($sql);$data['data']=$res->fetchAll(PDO::FETCH_ASSOC);$data['info']=array("dsn"=>$this->config->dsn,"dbname"=>$this->dbname,"table"=>$this->table,"sql"=>$sql);return $data;   }  public function insert(array $arrData) {$name = $values = '';$flag = $flagV = 1;$true = is_array( current($arrData) );//判断是否一次插入多条数据if($true) {//构建插入多条数据的sql语句foreach($arrData as $arr) {$values .= $flag ? '(' : ',(';foreach($arr as $key => $value) {if($flagV) {if($flag) $name .= "$key";$values .= "'$value'";$flagV = 0;} else {if($flag) $name .= ",$key";$values .= ",'$value'";}}$values .= ') ';$flag = 0;$flagV = 1;}} else {//构建插入单条数据的sql语句foreach($arrData as $key => $value) {if($flagV) {$name = "$key";$values = "('$value'";$flagV = 0;} else {$name .= ",$key";$values .= ",'$value'";}}$values .= ") ";}$sql = "insert into ".$this->dbname.'.'.$this->table." ($name) values $values";if( ($rs = $this->connection->exec($sql) ) > 0 ) {return array("dsn"=>$this->config->dsn,"dbname"=>$this->dbname,"table"=>$this->table,"sql"=>$sql);}return false;}public function query($sql){  return $this->connection->query($sql);  }
}

5、测试

使用主键id作为分表字段,那最好就不要使用自增了,可使用uuid

User.php (代码可滑动查看)

<?php
require 'Config.php';
require 'Model.php';
class User extends Model
{  protected $dbnamePrefix = 'cloude';  protected $tablePrefix = 'user';
}
//生成唯一uuid
function create_uuid($prefix = ""){    //可以指定前缀$str = md5(uniqid(mt_rand(), true));   $uuid  = substr($str,0,8) . '-';   $uuid .= substr($str,8,4) . '-';   $uuid .= substr($str,12,4) . '-';   $uuid .= substr($str,16,4) . '-';   $uuid .= substr($str,20,12);   return $prefix . $uuid;
}$userId=create_uuid();
$user = new User($userId);
$data=array('id'=>$userId,'name'=>'大明'.$userId,'password'=>'14e1b600b1fd579f47433b88e8d85291','sex'=>'男');
if($result=$user->insert($data)){echo '插入成功:','<pre/>';print_r($result);
}$condition=array("id"=>$userId);
$list=$user->select($condition);
if($list){echo '查询成功:','<pre/>';print_r($list);
}

6、结果
插入成功会返回插入到哪个库哪个表,查询成功返回从哪个库哪个表查的

分库分表注意事项:
1、维度问题
假如用户购买了商品,需 要将交易记录保存取来,如果按照用户的纬度分表,则每个用户的交易记录都保存在同一表中,所以很快很方便的查找到某用户的购买情况,但是某商品被购买的情 况则很有可能分布在多张表中,查找起来比较麻烦。

反之,按照商品维度分表,可以很方便的查找到此商品的购买情况,但要查找到买人的交易记录比较麻烦。

所以常见的解决方式有:
通过扫表的方式解决,此方法基本不可能,效率太低了。
记录两份数据,一份按照用户纬度分表,一份按照商品维度分表。
通过搜索引擎解决,但如果实时性要求很高,又得关系到实时搜索

2、避免分表join操作 因为关联的表有可能不在同一数据库中
3、避免跨库事务
避免在一个事务中修改db0中的表的时候同时修改db1中的表,一个是操作起来更复杂,效率也会有一定影响

4、分表宜多不宜少;这样做主要是为了尽量避免后期可能遇到的二次拆分。
5、尽量把同一组数据放到同一DB服务器上。
例如将卖家a的商品和交易信息都放到db0中,当db1挂了的时候,卖家a相关的东西可以正常使用。也就是说避免数据库中的数据依赖另一数据库中的数据

以上内容希望帮助到大家,需要更多文章可以关注公众号:PHP从入门到精通,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些PHP高级、架构视频资料和大厂PHP面试PDF免费获取,需要戳这里PHP进阶架构师>>>实战视频、大厂面试文档免费获取

mysql pdo 插入没效果_MySQL分库分表后用PHP如何来完美操作相关推荐

  1. mysql分库分表分页查询语句_MySQL分库分表分库后的查询(8th)

    前言 这边我们以使用python程序要展示一下再分库分表后,我们需要如何对数据库进行操作. python操作数据库 我们这边还是沿用之前的那5中:场景1:购买者下订单#!/usr/bin/env py ...

  2. MySQL分库分页_MySQL分库分表的分页查询解决方案

    问题的提出 我们知道,当我们的数据量达到一定数量时,需要将数据表进行水平拆分,从而满足大量数据的存储和查询,保证系统的可用性,但同时会出现另外一个问题就是,如果业务要查询"最近注册的第3页用 ...

  3. mysql分表后怎么索引_分库分表后的索引问题

    摘要 最近遇到一个慢sql,在排查过程中发现和分库分表后的索引设置有关系,总结了下问题. 问题 在进行应用健康度盘点时,发现有个慢sql 如下 select brandgoodid from bran ...

  4. 数据库分库分表后,如何部署上线?

    1. 引言 我们先来讲一个段子 面试官:"有并发的经验没?" 应聘者:"有一点." 面试官:"那你们为了处理并发,做了哪些优化?" 应聘者: ...

  5. mysql分表搜索引擎_MySql分库分表总结(转)

    为什么要分库分表 可以用说用到MySQL的地方,只要数据量一大, 马上就会遇到一个问题,要分库分表. 这里引用一个问题为什么要分库分表呢?MySQL处理不了大的表吗? 其实是可以处理的大表的.我所经历 ...

  6. mysql+join+分库分表_MySQL分库分表篇

    传统项⽬结构 数据库性能瓶颈: 1.数据库连接数有限 MySQL数据库默认100个连接.单机最⼤1500连接. 2.表数据量 1)表数量多,成百上千 2)单表数据,千万级别 3)索引,命中率问题,索引 ...

  7. mysql数据库分表备份脚本_MySQL分库分表备份脚本

    MySQL分库分表备份脚本 vim /data/mysqlback.sh #! /bin/bash BAKPATH=/data/mysql-back MYUSER=root MYPASS=" ...

  8. mysql分片库分页查询_Mysql分库分表

    一.数据库瓶颈 不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值.在业务Service来看就是,可用数据库连接少甚至无连接可用.接下来就 ...

  9. mysql分库分表配置命令_mysql分库分表中间件Heisenberg

    "trans_shard"> "trans_online, trans_content, trans_tb "dataNode="transDN ...

最新文章

  1. Oracle的连接与会话
  2. AttributeError: module ‘matplotlib’ has no attribute ‘artist’
  3. 通信人,请不要吝啬举手之劳
  4. OpenCV修养(一)——引入
  5. 数据库工作笔记008---pg_hba.conf entry for host “192.168.2.111”, user “gpadmin”, database “template1”, SSL
  6. 解读Go语言的2021:稳定为王
  7. linux安装软件无图标,linux安装的软件如何不固定在桌面图标 linux 桌面图标
  8. 嘻哈帝国第一季/全集Empire迅雷下载
  9. 华为 网络 链路捆绑
  10. 服务器如何从安全模式增加用户名,win10安全模式里怎么添加账户_win10 安全模式如何添加用户-win7之家...
  11. 你们都以落第为耻,我却以落第动心为耻
  12. 【cmake学习】cmake 引入第三方库(头文件目录、库目录、库文件)
  13. 张勋说:棒磨机断棒的几个可能原因
  14. 《LeetCode》数据结构入门板块
  15. 分享三套美团面试经历+简单答案
  16. https://sci-hub.io/ 吊炸天,各种论文随便下
  17. 原生开发什么意思_APP原生开发和混合开发的区别你了解多少
  18. ESP8266红外检测安全系统
  19. fluent二维叶型仿真_Fluent案例4【自然对流】
  20. ethos专用系统 登录 教程

热门文章

  1. 【kafka】 kafka 2.3 版本 生产者和消费者事务 案例
  2. 【ElasticSearch】Es 源码之 PeerRecoverySourceService 源码解读
  3. 【registry】registry 0.9 源码 在 windows下运行
  4. Maven : JsonMappingException: Incompatible Jackson version: 2.9.5
  5. Maven : maven工程libraries没有maven dependencies
  6. 95-190-444-源码-window-Trigger-EventTimeTrigger
  7. 【安全】java的Jaas授权与鉴权
  8. 【安全】Docker安装LDAP
  9. 06-windows下Orcale使用Database Configuration Assistant建立数据库
  10. 远行星号java 出错_打了势力争霸之后就出错了