zoukankan      html  css  js  c++  java
  • 按月分表(create table)

    PHP 按月分表控制台命令(yii2版)

    <?php
    /**
     * @Purpose: 按月分表脚本
     * @User: Chrdai
     * @Date: 2019/3/19
     * @Time: 15:23
     */
    namespace appcommands;
    
    use yiiconsoleController;
    
    class CreateTableController extends Controller
    {
        /**
         * @var string 数据库服务器
         */
        const HOST = '127.0.0.1';
    
        /**
         * @var string 用户名
         */
        const USERNAME = 'root';
    
        /**
         * @var string 密码
         */
        const PASSWORD = 'testpasswd';
    
        /**
         * @var string  数据库
         */
        const DBNAME = 'test';
    
        /**
         * @var string 默认方法
         */
        public $defaultAction = 'create-table-by-month';
    
    
        public function options($actionID)
        {
            return parent::options($actionID);
        }
    
        /**
         * @purpose: 准备表前缀和表结构
         * @author: Chrdai
         * @time: 2019-03-19
         * @return array
         */
        public function prepare()
        {
            $userPrefix = 'user_';
            $userSql = <<<EOF
    (
      id int(11) NOT NULL AUTO_INCREMENT,
      name varchar(32) NOT NULL DEFAULT '' COMMENT '姓名',
      created_at datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      updated_at datetime DEFAULT null COMMENT '更新时间',
      PRIMARY KEY (id)
    ) CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT '用户表';
    EOF;
    
            return [
                [
                    'table_prefix' => $userPrefix,
                    'sql' => $userSql,
                ],
            ];
        }
    
        /**
         * @purpose: 如果网络可用,则进行一次时间同步
         * @author: Chrdai
         * @time: 2019-03-19
         */
        public function updateToCurrentTime()
        {
            //ping 3 次
            passthru('ping baidu.com -c 3 >/dev/null 2>&1',$res);
            if($res === 0){
                system('ntpdate asia.pool.ntp.org && hwclock --systohc');
            }
        }
    
        /**
         * @purpose: 按月分表
         * #表命名方案:table_prefix_年月_序号
         * #每月的表1是保存1---15日的数据,表2是保存16--31日的数据
         * @author: Chrdai
         * @time: 2019-03-19
         */
        public function actionCreateTableByMonth()
        {
            //登录mysql
            $mysqlLoginInfo = '-h'.self::HOST.' -u'.self::USERNAME.' -p'.self::PASSWORD . ' -D'.self::DBNAME;
            $createHead = "CREATE TABLE IF NOT EXISTS ";
            $this->updateToCurrentTime();
            $arrTable = $this->prepare();
            $year = date('Y',time());
            $month = date('m',time());
            // 创建本月的表
            foreach($arrTable as $val){
                //每月2张表
                for($i = 1; $i <=2 ; $i ++){
                    $tableName = $val['table_prefix'] . $year . $month . '_' . $i;
                    $sql = end($val);
                    system("/usr/bin/mysql {$mysqlLoginInfo} -e "{$createHead} {$tableName} {$sql}"");
                }
            }
    
            //创建下个月的表,如果跨年需要单独处理
            if(intval($month) == 12){
                $nextYear = $year + 1;
                foreach($arrTable as $val){
                    for($i = 1; $i <=2 ; $i ++){
                        //下一年1月份的表名
                        $tableName = $val['table_prefix'] . $nextYear . '01_' . $i;
                        $sql = end($val);
                        system("/usr/bin/mysql {$mysqlLoginInfo} -e "{$createHead} {$tableName} {$sql}"");
                    }
                }
            }else{
                $nextMonth = intval($month) + 1;
                //下个月的表名
                $fullMonth = $nextMonth < 10 ? '0' . $nextMonth : $nextMonth;
                foreach($arrTable as $val){
                    for($i = 1; $i <=2 ; $i ++){
                        $tableName = $val['table_prefix'] . $year . $fullMonth . '_' . $i;
                        $sql = end($val);
                        system("/usr/bin/mysql {$mysqlLoginInfo} -e "{$createHead} {$tableName} {$sql}"");
                    }
                }
            }
        }
    }
    分表规则为:
    每月分两张表.

    1-15号为 table_prefix_Ym_1 ,
    16-31号为table_prefix_Ym_2 ,
    如:table_prefix_201903_1
    <?php
    /**
     * @purpose: 根据时间范围获取表名
     * @explain: 表名的分表规则是,每月分两张表,1-15号为 table_prefix_Ym_1 ,16-31号为table_prefix_2 , 如:table_prefix_201903_1
     * User: Chrdai
     * Date: 2019/3/5
     * Time: 18:08
     */
    
    class TablePrefix
    {
        /**
         * @const app调用记录表前缀
         */
        const PREFIX= 'table_prefix_';
    
        /**
         * @purpose:获取指定时间范围内的app调用记录表
         * @param int|string $starttime 开始时间
         * @param int|string $endtime 结束时间
         * @return array $tables 指定时间范围内的应用程序记录表
         */
        public static function getTableByDateRange($starttime,$endtime)
        {
            $tables = [];
            if(!empty($starttime)){
                $start = is_numeric($starttime) ? date('Ymd',$starttime) : date('Ymd',strtotime($starttime));
            }
            if(!empty($endtime)){
                $end = is_numeric($endtime) ? date('Ymd',$endtime) : date('Ymd',strtotime($endtime));
            }
            if(!empty($start) && !empty($end)){
                $prev = floor($start / 100);
                $next = floor($end / 100);
                //开始时间小于等于结束时间范围内的表都房间$tables
                while ($prev <= $next){
                    $tables[] = self::PREFIX . $prev. '_1';
                    $tables[] = self::PREFIX . $prev. '_2';
                    $prev = ($prev % 100 === 12) ? ((floor($prev/100)  + 1) * 100 +1) : $prev + 1; //对夸年的月份做特殊处理
                }
    
                //以15天为分界线,分上下月,去除重复的表
                if($start % 100 > 15){
                    array_shift($tables);
                }
                if($end % 100 <= 15){
                    array_pop($tables);
                }
            }
            return $tables;
        }
    }
    //获取表名
    $tables = TablePrefix::getTableByDateRange('2019-03-05 12:00:00','2019-03-05 14:00:00');
    //循环处理各个表中的数据
    $table = array_shift($tables); // 首先拿出第一张表中的数据
    while(true){
        __loop:
        
        //...... (每张表的业务逻辑)
        
        // 如果$tables中没有表了,则跳出循环,否则循环处理
        if(empty($tables)){
            break;
        }else{
            $table = array_shift($tables);
            goto __loop;
        }
    }

    此文为袋鼠(Chrdai)工作中所几记,如有转载请注明出处:https://www.cnblogs.com/chrdai/p/10551175.html

  • 相关阅读:
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车按键启动和蜂鸣器报警
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车指定花式动作
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车指定花式动作
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车指定花式动作
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
    asp中设置session过期时间方法总结
    asp中设置session过期时间方法总结
    ASP.NET关于Session_End触发与否的问题
  • 原文地址:https://www.cnblogs.com/chrdai/p/10551175.html
Copyright © 2011-2022 走看看