mysql 分区表_分享一份生产环境mysql数据库分区表改造方案

概述

简单分享下最近做的一个mysql数据库分区表改造方案,仅供参考。


思路:(假设在2020.7.21进行表分区改造)

没时间,就不画图说明了

1、创建与原始表一样结构的新表,新分区

2、往新表插入旧表在2020.7.20 00:00:00之前的数据

3、业务空闲时间段进行表切换

4、新表建索引、触发器等

5、数据补录(将原始表中超过2020.7.20 00:00:00的数据补录到新表)


一、创建新表及分区

注意分区键需在主键上,且不能为null

CREATE TABLE `t_att_dd_pushcard_info_range` (  `id` varchar(64) NOT NULL COMMENT 'ID',  `user_id` varchar(64) DEFAULT NULL COMMENT '员工ID',  `work_date` varchar(64) NOT NULL COMMENT '工作日',  `plan_id` varchar(64) DEFAULT NULL COMMENT '排班id',  `approve_id` varchar(64) DEFAULT NULL COMMENT '审批id,结果集中没有的话表示没有审批单',  ....  `patch_flag` varchar(1) DEFAULT NULL COMMENT '是否补卡 Y 是 N 否',  PRIMARY KEY (`id`,work_date),  KEY `idx_hwb1` (`user_id`,`check_type`,`work_date`) USING BTREE,  KEY `idx_work_date` (`work_date`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='钉钉打卡详情表'/*!50500 PARTITION BY RANGE  COLUMNS(work_date)(PARTITION p201909 VALUES LESS THAN ('2019-10-01') ENGINE = InnoDB, PARTITION p201910 VALUES LESS THAN ('2019-11-01') ENGINE = InnoDB, PARTITION p201911 VALUES LESS THAN ('2019-12-01') ENGINE = InnoDB, PARTITION p201912 VALUES LESS THAN ('2020-01-01') ENGINE = InnoDB, PARTITION p202001 VALUES LESS THAN ('2020-02-01') ENGINE = InnoDB, PARTITION p202002 VALUES LESS THAN ('2020-03-01') ENGINE = InnoDB, PARTITION p202003 VALUES LESS THAN ('2020-04-01') ENGINE = InnoDB, PARTITION p202004 VALUES LESS THAN ('2020-05-01') ENGINE = InnoDB, PARTITION p202005 VALUES LESS THAN ('2020-06-01') ENGINE = InnoDB, PARTITION p202006 VALUES LESS THAN ('2020-07-01') ENGINE = InnoDB, PARTITION p202007 VALUES LESS THAN ('2020-08-01') ENGINE = InnoDB, PARTITION p202008 VALUES LESS THAN ('2020-09-01') ENGINE = InnoDB, PARTITION p202009 VALUES LESS THAN ('2020-10-01') ENGINE = InnoDB, PARTITION p202010 VALUES LESS THAN ('2020-11-01') ENGINE = InnoDB, PARTITION p202011 VALUES LESS THAN ('2020-12-01') ENGINE = InnoDB, PARTITION p202012 VALUES LESS THAN ('2021-01-01') ENGINE = InnoDB, PARTITION p202101 VALUES LESS THAN ('2021-02-01') ENGINE = InnoDB, PARTITION p202102 VALUES LESS THAN ('2021-03-01') ENGINE = InnoDB) */
a02027cda82cdb80f94ebc0bd1e2f437.png

二、新表插入数据

insert into t_att_dd_pushcard_info_range select * from t_att_dd_pushcard_info  where work_date='2020-01-01 00:00:00' and work_date='2020-03-01 00:00:00' and work_date='2020-05-01 00:00:00' and work_date
b4a1d4d6eb16b9960540f25b44308769.png

三、表切换

alter table t_att_dd_pushcard_info rename to t_att_dd_pushcard_info_arch;alter table t_att_dd_pushcard_info_range rename to t_att_dd_pushcard_info;
f1ebd0ee1cdac61ff37e347eb9193aae.png

四、数据补录

insert into t_att_dd_pushcard_info select * from t_att_dd_pushcard_info_arch  where work_date>='2020-07-20 00:00:00'; 
036feb332e67ff792f39a65f8ea12ad8.png

五、检查分区

SELECTTABLE_SCHEMA,TABLE_NAME,PARTITION_NAME,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,DATA_LENGTH / 1024 / 1024 "DATA(MB)",INDEX_LENGTH / 1024 / 1024 "INDEX(MB)",CREATE_TIME,SUBPARTITION_NAME,PARTITION_ORDINAL_POSITION FROMINFORMATION_SCHEMA.PARTITIONS WHERETABLE_NAME='t_att_dd_pushcard_info'
08a66224a86e0b7214d0910d1f040947.png

六、sql改造

1、原sql

SELECTuser_id,class_id,className,isOffDutyFreeCheck,work_date,GROUP_CONCAT( userCheckTimeOn SEPARATOR ',' ) AS userCheckTimeOn,GROUP_CONCAT( userCheckTimeOff SEPARATOR ',' ) AS userCheckTimeOff,timeResultOn,timeResultOff,isExceedFix,normal_or_over,section_id,GROUP_CONCAT( patch_flag SEPARATOR ',' ) AS patch_flag FROM(SELECT DISTINCTt.user_id,t.class_id,sec.class_name AS className,sec.is_off_duty_free_check AS isOffDutyFreeCheck,t.work_date,t.user_check_time AS userCheckTimeOn,'' AS userCheckTimeOff,t.check_type,t.time_result AS timeResultOn,'' AS timeResultOff,is_exceed_fix isExceedFix,t.normal_or_over,t.section_id,patch_flag FROMt_att_dd_pushcard_info tLEFT JOIN t_att_dd_attgroup_sec_info sec ON t.`class_id` = sec.`class_id` WHEREt.check_type = 'OnDuty'     AND t.`user_id` IS NOT NULL     AND DATE_FORMAT ( t.work_date, '%Y-%m-%d' ) >= DATE_FORMAT ( '2020-07-01 09:44:37', '%Y-%m-%d' ) AND DATE_FORMAT ( t.work_date, '%Y-%m-%d' ) <= DATE_FORMAT ( '2020-07-21 09:44:37', '%Y-%m-%d' ) UNION ALLSELECT DISTINCTt.user_id,t.class_id,sec.class_name AS className,sec.is_off_duty_free_check AS isOffDutyFreeCheck,t.work_date,'' AS userCheckTimeOn,t.user_check_time AS userCheckTimeOff,t.check_type,'' AS timeResultOn,t.time_result AS timeResultOff,is_exceed_fix isExceedFix,t.normal_or_over,t.section_id,patch_flag FROMt_att_dd_pushcard_info tLEFT JOIN t_att_dd_attgroup_sec_info sec ON t.`class_id` = sec.`class_id` WHEREt.check_type = 'OffDuty' AND t.`user_id` IS NOT NULL AND DATE_FORMAT ( t.work_date, '%Y-%m-%d' ) >= DATE_FORMAT ( '2020-07-01 09:44:37', '%Y-%m-%d' ) AND DATE_FORMAT ( t.work_date, '%Y-%m-%d' ) <= DATE_FORMAT ( '2020-07-21 09:44:37', '%Y-%m-%d' ) ) card GROUP BYuser_id,class_id,section_id,className,isOffDutyFreeCheck,work_date,normal_or_over
c5fe669d608d6f5a0492f696830d6666.png

2、改造后sql

SELECTuser_id,class_id,className,isOffDutyFreeCheck,work_date,GROUP_CONCAT( userCheckTimeOn SEPARATOR ',' ) AS userCheckTimeOn,GROUP_CONCAT( userCheckTimeOff SEPARATOR ',' ) AS userCheckTimeOff,timeResultOn,timeResultOff,isExceedFix,normal_or_over,section_id,GROUP_CONCAT( patch_flag SEPARATOR ',' ) AS patch_flag FROM(SELECT DISTINCTt.user_id,t.class_id,sec.class_name AS className,sec.is_off_duty_free_check AS isOffDutyFreeCheck,t.work_date,t.user_check_time AS userCheckTimeOn,'' AS userCheckTimeOff,t.check_type,t.time_result AS timeResultOn,'' AS timeResultOff,is_exceed_fix isExceedFix,t.normal_or_over,t.section_id,patch_flag FROM(select * from t_att_dd_pushcard_info r where r.work_date>='2020-07-01 09:44:37' and r.work_date <='2020-07-21 09:44:37')tLEFT JOIN t_att_dd_attgroup_sec_info sec ON t.`class_id` = sec.`class_id` ) card GROUP BYuser_id,class_id,section_id,className,isOffDutyFreeCheck,work_date,normal_or_over
6a07f48a5143aa5ccacd3e58078469ae.png

后面会分享更多devops和DBA方面内容,感兴趣的朋友可以关注下!

638b9ee749c1dc792782bdf4005f36eb.gif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 表分区是一种将大型表水平分成多个部分的技术,这有助于提高查询和数据管理的效率。在 MySQL 中,可以使用 RANGE、LIST、HASH 和 KEY 四种分区类型来定义分区方式。 下面是 MySQL 表分区的详细操作步骤: 1. 创建表时定义分区方式 在创建表的时候,可以指定表的分区方式。例如,使用 RANGE 分区方式将表按照数值范围进行分区: ``` CREATE TABLE mytable ( id INT, value INT ) PARTITION BY RANGE (value) ( PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (MAXVALUE) ); ``` 2. 插入数据 向表中插入数据时,MySQL 会自动将数据插入到正确的分区中。例如,插入一个 value 值为 5 的数据: ``` INSERT INTO mytable (id, value) VALUES (1, 5); ``` 3. 查询数据 在查询数据时,MySQL 可以仅查询特定的分区,而不必扫描整个表。例如,查询 value 值在 10 到 20 之间的数据: ``` SELECT * FROM mytable PARTITION (p1); ``` 4. 修改分区 可以使用 ALTER TABLE 语句修改表的分区方式,例如,将表从 RANGE 分区方式修改为 HASH 分区方式: ``` ALTER TABLE mytable PARTITION BY HASH(value) PARTITIONS 4; ``` 5. 合并分区 可以使用 ALTER TABLE 语句将相邻的分区合并为一个分区,例如,将分区 p1 和 p2 合并为一个分区: ``` ALTER TABLE mytable COALESCE PARTITION p1, p2 INTO p3; ``` 6. 删除分区 可以使用 ALTER TABLE 语句删除表的某个分区,例如,删除分区 p0: ``` ALTER TABLE mytable DROP PARTITION p0; ``` 以上就是 MySQL 表分区的详细操作步骤,可以根据实际需求选择不同的分区方式来提高查询和数据管理的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值