当前位置: 首页 > news >正文

MySql创建分区表并且按月分区

前言

        在mysql中,按月份分区,再使用分区字段时间来查询数据将会很快,因为这样只需要扫描指定的分区。因此,在处理大量数据时,使用分区表是一个非常好的选择。

1、创建表,并使用RANGE COLUMNS分区

        按创建时间create_time字段分区;分区名使用p0、p1、p2、p3 .. 的形式;create_time字段小于2019-01-01的数据将进入p0 分区,依次类推。

CREATE TABLE "box_fenqu" (
  "id" bigint(36) NOT NULL AUTO_INCREMENT COMMENT '主键',
  "create_by" varchar(50) DEFAULT NULL COMMENT '创建人',
  "create_time" datetime NOT NULL COMMENT '创建日期',
  "update_by" varchar(50) DEFAULT NULL COMMENT '更新人',
  "update_time" datetime DEFAULT NULL COMMENT '更新日期',
  "sys_org_code" varchar(64) DEFAULT NULL COMMENT '所属部门',
  "status" int(10) DEFAULT '0' COMMENT '状态',
  "number" varchar(32) DEFAULT NULL COMMENT '编号',
  "zi_number" varchar(32) DEFAULT NULL COMMENT '自编号',
  "house_address" varchar(32) DEFAULT NULL COMMENT '仓库地址',
  "sb_number" varchar(32) DEFAULT NULL COMMENT '设备id',
  "point_id" varchar(32) DEFAULT NULL COMMENT '投放点id',
  "point" varchar(32) DEFAULT NULL COMMENT '投放点',
  "confirm" int(32) DEFAULT '0' COMMENT '商户/企业用户确认入库,默认为0(未确认)1是已确认',
  "last_point" varchar(32) DEFAULT NULL COMMENT '最近一次投放点名',
  PRIMARY KEY ("id","create_time") USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2120001 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC
 PARTITION BY RANGE  COLUMNS(create_time)
(PARTITION p0 VALUES LESS THAN ('2019-01-01') ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN ('2019-02-01') ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN ('2019-03-01') ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN ('2019-04-01') ENGINE = InnoDB,
 PARTITION p4 VALUES LESS THAN ('2019-05-01') ENGINE = InnoDB,
 PARTITION p5 VALUES LESS THAN ('2019-06-01') ENGINE = InnoDB,
 PARTITION p6 VALUES LESS THAN ('2019-07-01') ENGINE = InnoDB,
 PARTITION p7 VALUES LESS THAN ('2019-08-01') ENGINE = InnoDB,
 PARTITION p8 VALUES LESS THAN ('2019-09-01') ENGINE = InnoDB,
 PARTITION p9 VALUES LESS THAN ('2019-10-01') ENGINE = InnoDB,
 PARTITION p10 VALUES LESS THAN ('2019-11-01') ENGINE = InnoDB,
 PARTITION p11 VALUES LESS THAN ('2019-12-01') ENGINE = InnoDB,
 PARTITION p12 VALUES LESS THAN ('2020-01-01') ENGINE = InnoDB,
 PARTITION p13 VALUES LESS THAN ('2020-02-01') ENGINE = InnoDB,
 PARTITION p14 VALUES LESS THAN ('2020-03-01') ENGINE = InnoDB,
 PARTITION p15 VALUES LESS THAN ('2020-04-01') ENGINE = InnoDB,
 PARTITION p16 VALUES LESS THAN ('2020-05-01') ENGINE = InnoDB,
 PARTITION p17 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) 

2、创建存储过程proc_create_partition

        创建存储过程proc_create_partition,用它来直接对box_fenqu表进行分区。其实就是将分区名加1,如p2加1就是p3;指定的日期范围就是往后面进一个月,保证最新的分区总是MAXVALUES的 ,如20200401就变成20200401和20200501,其中20200401指定范围,20200501为MAXVALUES。

CREATE DEFINER="root"@"%" PROCEDURE "proc_create_partition"(in_tbname VARCHAR(64))
BEGIN

SELECT DATABASE() INTO @dbname;

SET @tbname = in_tbname;

#查询表的最近一次分区的名字,这里按自然数递增的。比如0,1,2,4。去掉 p
SELECT
    REPLACE (partition_name, 'p', '') INTO @PMAX
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = @dbname
AND table_name = @tbname
ORDER BY
    partition_ordinal_position DESC
LIMIT 1;

#查询表的最近一次分区的指定时间,比如最近时间的分区时 2020.04.01
SELECT
REPLACE(partition_description, '\'', '') INTO @DNAME
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = @dbname
AND table_name = @tbname
ORDER BY
    partition_ordinal_position DESC
LIMIT 1, 1;


SET @t=CONCAT('alter table `',@dbname,'`.',@tbname,' reorganize partition p',@PMAX,
                          ' into(partition p',@PMAX,' values less than (''',date(DATE_ADD(@DNAME,INTERVAL 1 MONTH)),'''),',
                            'partition p',@PMAX+1,' values less than MAXVALUE)');

SELECT @t;
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

COMMIT;
END

这样传入box_fenqu表名即可进行增加分区了: CALL proc_create_partition('box_fenqu')。

3、创建mysql事件

         创建mysql事件,定时调度分区;下面的事件到的意思就是从2020-05-03 00:00:00开始,每过一个月就执行下CALL proc_create_partition('box_fenqu')。

CREATE DEFINER=`root`@`%` EVENT `e_create_partition` 
ON SCHEDULE EVERY 1 MONTH STARTS '2020-05-03 00:00:00' 
ON COMPLETION PRESERVE DISABLE 
DO CALL proc_create_partition('box_fenqu')

4、动态增加分区

        如果有多个表需要都需要定时的动态增加分区的话,就可以再写个存储如下,这个存储过程将对当前库下所有分区表都进行遍历,然后增加分区。

CREATE DEFINER="root"@"%" PROCEDURE "proc_create_partition_all"()
BEGIN

  DECLARE tbname varchar(32);
  DECLARE tmpSql varchar(256);
  DECLARE done INT DEFAULT FALSE ;

#查询已手动分区的表
    DECLARE part_cursor CURSOR FOR (SELECT DISTINCT table_name FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = DATABASE() AND partition_expression IS NOT NULL AND table_name NOT LIKE '%bak');
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

#循环对表添加分区
    OPEN part_cursor;
        myLoop: LOOP
            FETCH part_cursor INTO tbname;
            IF done THEN 
                LEAVE myLoop;
            END IF;
            #调用分区存储过程
            CALL proc_create_partition(tbname);

            COMMIT;
        END LOOP myLoop;
    CLOSE part_cursor;
    
END

5、开启事件

alter event `e_create_partition` enable;

6、查询数据

        查询有数据的最新日期/月份

select REPLACE(partition_description, '\'', '') date from INFORMATION_SCHEMA.PARTITIONS where TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='box_fenqu' AND table_rows != 0
ORDER BY REPLACE(partition_description, '\'', '') desc limit 1

        查询有数据的数据条数 

select table_rows from INFORMATION_SCHEMA.PARTITIONS where TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='box_fenqu' AND table_rows != 0
ORDER BY REPLACE(partition_description, '\'', '') desc limit 1

        查询各个分区数据情况

SELECT
    PARTITION_NAME AS '分区名',
    TABLE_ROWS AS '记录数' ,
        PARTITION_DESCRIPTION '范围'
FROM
    information_schema.PARTITIONS 
WHERE
    table_schema = 'test' 
    AND table_name = 'box_fenqu';

参考文档:

mysql 分区实践之按月份分区,定时增加分区和删除分区 - 简书

MySQL 创建分区表并且按月分区

相关文章:

  • 数据库:一文掌握 Elasticsearch 的各种指令(Elasticsearch指令备忘)
  • 用户态内核态切换
  • 什么?获取到了未知的复位原因?
  • SOFABoot-07-版本查看
  • Linux系统管理与编程08:任务驱动综合应用
  • SAP SD学习笔记33 - 预詑品(寄售物料),预詑品引渡(KB),预詑品出库(KE)
  • S32k3XX MCU时钟配置
  • Gone v2 使用 goner/viper/remote链接远程的配置中心,支持etcd、consul、firestore、nats
  • 【Linux 下的 bash 无法正常解析, Windows 的 CRLF 换行符问题导致的】
  • 记忆力训练day24
  • C语言入门教程100讲(3)代码注释
  • 【免费】2000-2019年各省地方财政印花税数据
  • k8s--集群内的pod调用集群外的服务
  • 无法写入文件:(FileSystemError): Error: EPERM: operation not permitted, open...)
  • 【即插即用涨点模块】LSK大选择性核:自适应地捕捉遥感图像目标,实现暴力涨点【附源码+注释】
  • Android Compose 线性布局(Row、Column)源码深度剖析(十)
  • 【C#】WinForm自定义控件及窗体
  • Shell正则表达式
  • Java锁等待唤醒机制
  • 【Linux】交叉编译2
  • 上海市重大工程一季度开局良好,崇明线等按既定计划加快建设
  • 国务院关税税则委员会公布公告调整对原产于美国的进口商品加征关税措施
  • 人才争夺战,二三线城市和一线城市拼什么?洛阳官方调研剖析
  • 回望乡土:对媒介化社会的反思
  • 巴军事行动致印度70%电网瘫痪
  • 上海消防全面推行“检查码”,会同相关部门推行“综合查一次”