ThinkPHP處理海量資料分表機制詳細代碼
應用ThinkPHP內建的分表演算法處理百萬級使用者資料. 資料表: house_member_0 house_member_1 house_member_2 house_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; } }
?