按月分表(create table)


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

<?php /** * @Purpose: 按月分表脚本 * @User: Chrdai * @Date: 2019/3/19 * @Time: 15:23 */ namespace app\commands; use yii\console\Controller; 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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM