MySQL:创建分区, 按天自动分区

分区表 按天自动分区

创建测试数据库

create database csl_test character set utf8 collate utf8_unicode_ci;

创建测试表

注:要分区的字段 需要为主键。

use csl_test; # 切换到刚刚创建的测试数据库

create table t_partition_test (
    pk_id bigint(20) not null auto_increment,
    time datetime not null,
    msg varchar(200),
    primary key (pk_id,time)
)engine=innodb default charset=utf8 collate utf8_unicode_ci comment="test partition";

插入测试数据

insert into t_partition_test(time,msg) values
    ('2021-02-01 13:34:23',"20210201133423"),
    ('2021-02-02 14:23:13',"20210202142313");

手动分区

在自动分区前,需对表进行手动分区,这样自动分区才能进行。

分区字段应为主键包含字段,不可为索引。
可使用该命令修改主键字段
alter table t_partition_test drop primary key, add primary key (pk_id, time);

批量分区

alter table t_partition_test partition by range columns(time)(
    partition p20210201 values less than('2021-02-02'),
    partition p20210202 values less than('2021-02-03'),
    partition p20210203 values less than('2021-02-04')
);

单条分区

alter table t_partition_test add partition (partition p20210201 values less than ('2021-02-02') );

删除分区

由于数据是存放在分区中,所以删除分区 也会删除 对应分区的数据。

alter table t_partition_test drop partition p20210201;

查看表分区

select partition_name,partition_description as val from information_schema.partitions
where table_name = 't_partition_test' and table_schema = 'csl_test';

创建增加删除分区的存储过程

-- 定义mysql提交查询语句 结束标识 为 $$
delimiter $$
DROP PROCEDURE IF EXISTS p_partition_test # 创建过程 p_partition_test
$$
CREATE PROCEDURE p_partition_test()
BEGIN
  DECLARE v_sysdate date; # 声明 当前时间
  DECLARE v_mindate date; # 声明 目前分区的最小值
  DECLARE v_maxdate date; # 声明 目前分区值中的最大值
  DECLARE v_pt varchar(20); # 声明 分区名称 数字部分
  DECLARE v_maxval varchar(20); # 声明 最大值
  DECLARE i int; # 声明 ??
  
  -- 增加新分区
  -- select into A from B 用法;A表作为临时表,不存在。 
  -- 不同于insert into A select from B,A必须存在。
  SELECT max(cast(replace(partition_description, '''', '') AS date)) AS val
  INTO   v_maxdate
  FROM   INFORMATION_SCHEMA.PARTITIONS
  WHERE  TABLE_NAME = 't_partition_test' AND TABLE_SCHEMA = 'csl_test';
  
  set v_sysdate = sysdate(); # 赋值v_sysdate为当前时间
  
  -- INTERVAL 时间计算的关键字
  WHILE v_maxdate <= (v_sysdate + INTERVAL 3 DAY) DO
    SET v_pt = date_format(v_maxdate ,'%Y%m%d');
    SET v_maxval = date_format(v_maxdate + INTERVAL 1 DAY, '%Y-%m-%d');
    SET @sql = concat('alter table t_partition_test add partition (partition p', v_pt, ' values less than(''', v_maxval, '''))');
    -- SQL语句预处理,在对于反复调用相同或极度相似的语句,进行预处理会优化处理速度,我感觉这里的用法应该没有效果
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    -- 删除预处理
    DEALLOCATE PREPARE stmt;
    SET v_maxdate = v_maxdate + INTERVAL 1 DAY; # 最大值 加一操作
  END WHILE;
  
  --删除旧分区
  SELECT min(cast(replace(partition_description, '''', '') AS date)) AS val
  INTO   v_mindate
  FROM   INFORMATION_SCHEMA.PARTITIONS
  WHERE  TABLE_NAME = 't_partition_test' AND TABLE_SCHEMA = 'csl_test';
    
  -- 删除一年前的旧分区
  WHILE v_mindate <= (v_sysdate - INTERVAL 1 YEAR) DO
    SET v_pt = date_format(v_mindate - INTERVAL 1 DAY,'%Y%m%d');
    SET @sql = concat('alter table t_partition_test drop partition p', v_pt);
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    SET v_mindate = v_mindate + INTERVAL 1 DAY;
  END WHILE;
 
END$$
-- 重新定义 MySQL提交查询语句的 结束标识 为 ;
delimiter ;

手动调用存储过程

call p_partition_test; # call p_partition_test();

开启事件

mysql默认是关闭定时任务

查看定时任务是否开启,OFF是没有开启:

show variables like '%event_scheduler%';
-- 或者
select @@event_scheduler;

临时开启定时任务(重启之后,配置会回复)

set global event_scheduler = 1;

永久开启,修改配置文件 my.cnf,

event_scheduler=ON;

创建event事件

delimiter $$
drop event if exists auto_pt $$
create event auto_pt
on schedule
-- every 1 minute
every 1 day
starts '2021-02-01 13:19:02'
do
BEGIN
    call p_partition_test();
END$$
delimiter ;
posted @ 2023-07-16 19:31  钢板意志  阅读(1518)  评论(0编辑  收藏  举报