zoukankan      html  css  js  c++  java
  • mysql大数据分表记录app用户的坐标数据

    最近提到一个需求。需要记录app用户在使用app中的移动轨迹,即坐标值。每分钟上传一次XY坐标,有点类似跑步软件的描线轨迹。

    不考虑app如何获取,反正api只要接受到坐标数据 就记录下来保存到数据库。接口接收3个参数X,Y,uid

    1,建个新库。test 无论你是云DB还是同服务器下都可以

    1 'DB_CONFIG2'=>array(
    2      'db_type'=>'mysql',
    3      'db_user'=>'root',
    4      'db_pwd'=>'',
    5      'db_host'=>'localhost',
    6      'db_port'=>'3306',
    7      'db_name'=>'test',
    8  ),

    2,建一个保存自增主键ID的表

    1 CREATE TABLE `create_id` (
    2   `id` bigint(20) NOT NULL AUTO_INCREMENT,
    3   PRIMARY KEY (`id`)
    4 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='自增ID表';

    3,附上主要代码

      1 class TestAction extends Action {
      2    
      3     function _initialize(){
      4         $this->db_2= M()->db(2,"DB_CONFIG2");
      5         $this->union_sql="CREATE TABLE IF NOT EXISTS `%s` (
      6   `id` int(11) NOT NULL,
      7   `longitude` decimal(10,6) NOT NULL COMMENT '经度',
      8   `latitude` decimal(10,6) NOT NULL COMMENT '纬度',
      9   `addtime` int(11) NOT NULL COMMENT '添加时间',
     10   `uid` int(11) NOT NULL COMMENT '用户ID',
     11   PRIMARY KEY (`id`)
     12 ) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 INSERT_METHOD=LAST UNION=(`%s`);";
     13         $this->num_sql="CREATE TABLE IF NOT EXISTS `%s` (
     14   `id` int(11) NOT NULL,
     15   `longitude` decimal(10,6) NOT NULL COMMENT '经度',
     16   `latitude` decimal(10,6) NOT NULL COMMENT '纬度',
     17   `addtime` int(11) NOT NULL COMMENT '添加时间',
     18   `uid` int(11) NOT NULL COMMENT '用户ID',
     19   PRIMARY KEY (`id`)
     20 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
     21         
     22     }
     23 
     24     public function index() {
     25        $uid=228; 
     26        $id = 10000099;
     27        //$id = $this->create_id();//生成自增ID
     28        //$uid=trim($_GET['uid']);
     29        $union_table_name="point_".$uid;//总表表名
     30        //新增记录分配分表名
     31        $num_table_name= $this->get_data_table($uid,$id);
     32        //分表名拼接
     33        $union_table_string=$this->get_union_string($uid,$id);
     34        //分表语句 
     35        $num_sql=sprintf($this->num_sql,$num_table_name);
     36        $this->execute($num_sql);//新建分表
     37        //总表语句  
     38        $union_sql=sprintf($this->union_sql,$union_table_name,$union_table_string);    
     39        echo $union_sql;
     40        $re1= $this->execute($union_sql);//创建总表
     41        echo ($this->db_2->getDbError());
     42       
     43        //新增记录
     44        $re=$this->execute("INSERT INTO $num_table_name (`id`, `longitude`, `latitude`, `addtime`, `uid`) VALUES ('$id', '1111.000000', '2222.000000', '22222', '$uid');");
     45        
     46        if($re){
     47            echo json_encode(array("status"=>1,"info"=>true));
     48        }else{
     49            echo json_encode(array("status"=>0,"info"=>false));
     50        }
     51        
     52        
     53     }
     54      
     55    
     56     /**
     57      * 创建一个自增主键
     58      * @return int
     59      */
     60     private function create_id(){
     61       $sql = "insert into create_id (id) values('')";
     62       $this->db_2->execute($sql);
     63       return $this->db_2->getLastInsID();
     64     }
     65     
     66     /**
     67      * 获得表名
     68      * @return string
     69      */
     70     private function get_data_table($uid=null,$id=null){
     71         if(empty($uid)||empty($id)){
     72             return false;
     73         }
     74         return 'point_'.$uid.'_'.$this->get_table_num($id);
     75     }
     76     
     77     /**
     78      * 获得记录所在表序号
     79      * @param  $id  记录ID
     80      * @param  $max 表最大记录数
     81      * @return int
     82      */
     83     private function get_table_num($id,$max=10000000){
     84         $num = ($id<$max) ? 1 : intval($id/$max); //整除取整,默认1
     85         $add =  ($id%$max)>0 && ($id>$max)  ?1:0;//有余数,序号加1
     86         return $num+$add;
     87     }
     88     
     89     /**
     90      * 判断表是否存在
     91      */
     92     private function table_exit_create($table=null){
     93      return $this->db_2->query("show tables like '%{$table}%'"); 
     94 //       return $this->db_2->query("desc {$table}"); 
     95     }
     96     
     97     
     98     /**
     99      * 建表
    100      * @return bool 
    101      */
    102     private function execute($sql){
    103         return $this->db_2->execute($sql); 
    104     }
    105     
    106     /**
    107      * 生成拼接分表名字符串
    108      * @param type $uid
    109      * @param type $id
    110      * @return string
    111      */
    112     private function get_union_string($uid=null,$id=null){
    113        $res = $this->table_exit_create("point_".$uid."_");
    114        if($res){
    115            if(count($res)>1){
    116                $arr=array();
    117                foreach($res as $v){
    118                    $arr[]=$v["Tables_in_test (%point_".$uid."_%)"];
    119                }
    120               $str= implode(',',$arr);
    121            }else{
    122             $str= "point_".$uid."_".$this->get_table_num($id);  
    123            }
    124         }else{
    125             $str= "point_".$uid."_".$this->get_table_num($id);
    126         }
    127         
    128          return $str;
    129       
    130        
    131     }

     4,分析

    原理非常简单。

    api接受到参数 -》主键表产生一个主键-》判断主键范围,分配分表名-》创建分表,并把这次接受参数插入分表(注意:所有分表的主键字段必须由主键表产生,确保唯一性)

    -》创建总表(必须是ENGINE=MRG_MyISAM),把分表union关联起来,方便查询

    分表必须MyISAM引擎,主键非自增

    补充:1,注意完善参数验证 。UID真实性等

         2,每个分表我取1千万,更大的没有测试。

    参考文章:百度来的http://soft.chinabyte.com/database/72/12620572.shtml

  • 相关阅读:
    信号之可重入函数
    信号的发送
    守护进程详解以及start-stop-daemon命令
    信号基本概念
    常用进程调度算法(转)
    malloc/free与new/delete的区别(转)
    IP地址转换
    exec系列函数详解
    fork函数拓展
    leetcode第156场周赛5205
  • 原文地址:https://www.cnblogs.com/luojianqun/p/4916470.html
Copyright © 2011-2022 走看看