找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2219|回复: 0

[教程] ThinkPHP处理海量数据分表机制详细代码及说明

[复制链接]
发表于 2013-4-13 21:08:52 | 显示全部楼层 |阅读模式 来自 中国–广东–湛江

  1. 应用ThinkPHP内置的分表算法处理百万级用户数据.
  2.   数据表:
  3.   house_member_0
  4.   house_member_1
  5.   house_member_2
  6.   house_member_3
  7.   模型中
  8.   class MemberModel extends AdvModel {
  9.   protected $partition =  array('field'=>'username','type'=>'id','num'=>'4');
  10.   public function getDao($data=array()) {
  11.   $data = empty($data) ? $_POST : $data;
  12.   $table = $this->getPartitionTableName($data);
  13.   return $this->table($table);
  14.   }
  15.   }
  16.   方法中
  17.   class MemberAction extends BaseAction {
  18.   public function login() {
  19.   if($this->isPost()) {
  20.   $this->validToken();
  21.   $dao = D('Member')->getDao();
  22.   $res = $dao->where('username = '.$_POST['username'])->find();
  23.   // output 为自定义方法
  24.   // $isAjax - bool
  25.   $this->output(false);
  26.   }
  27.   $this->display();
  28.   }
  29.   }
  30.   /**
  31.   +----------------------------------------------------------
  32.   * 得到分表的的数据表名
  33.   +----------------------------------------------------------
  34.   * @access public
  35.   +----------------------------------------------------------
  36.   * @param array $data 操作的数据
  37.   +----------------------------------------------------------
  38.   * @return string
  39.   +----------------------------------------------------------
  40.   */
  41.   public function getPartitionTableName($data=array()) {
  42.   // 对数据表进行分区
  43.   if(isset($data[$this->partition['field']])) {
  44.   $field = $data[$this->partition['field']];
  45.   switch($this->partition['type']) {
  46.   case 'id':
  47.   // 按照id范围分表
  48.   $step = $this->partition['expr'];
  49.   $seq = floor($field / $step)+1;
  50.   break;
  51.   case 'year':
  52.   // 按照年份分表
  53.   if(!is_numeric($field)) {
  54.   $field = strtotime($field);
  55.   }
  56.   $seq = date('Y',$field)-$this->partition['expr']+1;
  57.   break;
  58.   case 'mod':
  59.   // 按照id的模数分表
  60.   $seq = ($field % $this->partition['num'])+1;
  61.   break;
  62.   case 'md5':
  63.   // 按照md5的序列分表
  64.   $seq = (ord(substr(md5($field),0,1)) % $this->partition['num'])+1;
  65.   break;
  66.   default :
  67.   if(function_exists($this->partition['type'])) {
  68.   // 支持指定函数哈希
  69.   $fun = $this->partition['type'];
  70.   $seq = (ord(substr($fun($field),0,1)) % $this->partition['num'])+1;
  71.   }else{
  72.   // 按照字段的首字母的值分表
  73.   $seq = (ord($field{0}) % $this->partition['num'])+1;
  74.   }
  75.   }
  76.   return $this->getTableName().'_'.$seq;
  77.   }else{
  78.   // 当设置的分表字段不在查询条件或者数据中
  79.   // 进行联合查询,必须设定 partition['num']
  80.   $tableName = array();
  81.   for($i=0;$i<$this->partition['num'];$i++)
  82.   $tableName[] = 'SELECT * FROM '.$this->getTableName().'_'.$i;
  83.   $tableName = '( '.implode(' UNION ',$tableName).') AS '.$this->name;
  84.   return $tableName;
  85.   }
  86.   }
复制代码

发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;

如何回报帮助你解决问题的坛友,好办法就是点击帖子下方的评分按钮给对方加【金币】不会扣除自己的积分,做一个热心并受欢迎的人!

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则 需要先绑定手机号

关闭

站长推荐上一条 /1 下一条

QQ|侵权投诉|广告报价|手机版|小黑屋|西部数码代理|飘仙建站论坛 ( 豫ICP备2022021143号-1 )

GMT+8, 2024-12-23 03:54 , Processed in 0.038128 second(s), 9 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表