首页 > PHP > ThinkPHP海量数据分表机制详细代码及说明

ThinkPHP海量数据分表机制详细代码及说明

2011年2月23日 admin 发表评论 阅读评论

应用ThinkPHP内置的分表算法处理百万级用户数据.

数据表:
house_member_0
house_member_1
house_member_2
house_member_3

模型:

1
2
3
4
5
6
7
8
9
10
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);
    }
}


方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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();
    }
}

ThinkPHP/Lib/Think/Core/Model/AdvModel.class.php 文件 getPartitionTableName 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
     +----------------------------------------------------------
     * 得到分表的的数据表名
     +----------------------------------------------------------
     * @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;
        }
    }

原文转自:http://lvtao.net/showarticle.php?articleid=1066&p=1

分类: PHP 标签: , ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.