• 按月分表(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

  • 相关阅读:
    javascript私有静态成员
    javascript公有静态成员
    javascript沙箱模式
    javascript构造函数模块
    javascript模块模式
    javascript私有方法揭示为公有方法
    javascript命名空间
    javascript构造函数强制使用new
    javascript惰性函数
    javascript柯里化
  • 原文地址:https://www.cnblogs.com/chrdai/p/10551175.html
Copyright © 2020-2023  润新知