MySQL数据库表分区

1.背景

当前数据库中,数据库表已经存在,同时该数据库表的数据还在每天不断增长。因为数据库表太大,导致检索过程耗时,为提高检索效率,故对相关数据库表进行分区处理。

2.MySQL分区

分区就是将一个表分解成多个区块进行操作和保存,从而降低每次操作的数据,提高性能。

而对应用来说是透明的,从逻辑上看是只有一个表,但在物理上这个表可能是由多个物理分区组成的,每个分区都是一个独立的对象,可以进行独立处理

四种常见的分区类型:

  • RANGE分区:最为常用,基于属于一个给定连续区间的列值,把多行分配给分区。最常见的是基于时间字段。

  • LIST分区:LIST分区和RANGE分区类似,区别在于LIST是枚举值列表的集合,RANGE是连续的区间值的集合。

  • HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式。

  • KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

3.示例

3.1 RANGE分区

情景:现有hourdb数据库表,想要基于该数据库表的time字段进行分区。

实现:

sql 复制代码
-- 1.对hourdb表进行分区
-- 分区规则:
-- 2019年及之前
-- 2020年上半年--2020年下半年
-- 2021年上半年--2021年下半年
-- 2022年上半年--2022年下半年
-- 2023年上半年--2023年下半年
-- 2024年上半年--2024年下半年
-- 2025年上半年--2025年下半年
-- 2026年及之后

-- 基于time字段产生time_year_month字段,time_year_month=year*100+month
alter table hourdb add column time_year_month int generated always 
as(year(STR_TO_DATE(time,'%Y-%m-%d %H:%i:%s'))*100+month(STR_TO_DATE(time,'%Y-%m-%d %H:%i:%s'))) 
stored;

-- 创建新的分区表hourdb_partitioned,相比较原hourdb表,增加time_year_month字段
create table if not exists `hourdb_partitioned` (
 `senid` decimal(38,0) comment '传感器点号',
 `time` varchar(255) comment '时标',
 `v` decimal(11,3) comment '整点值',
 `avgv` decimal(11,3) comment '平均值',
 `maxv` decimal(11,3) comment '最大值',
 `maxt` varchar(255) comment '最大值发生时间',
 `minv` decimal(11,3) comment '最小值',
 `mint` varchar(255) comment '最小值发生时间',
 `s` decimal(38,0) comment '整点值标识',
 `avgs` decimal(38,0) comment '平均值标识',
 `maxs` decimal(38,0) comment '最大值标识',
 `mins` decimal(38,0) comment '最小值标识',
 `span` decimal(38,0) comment '计算时段',
 time_year_month int generated always 
 as(year(STR_TO_DATE(time,'%Y-%m-%d %H:%i:%s'))*100+month(STR_TO_DATE(time,'%Y-%m-%d %H:%i:%s'))) stored
)comment '小时数据信息'
partition by range(time_year_month)(
 partition p202000 values less than (202001) comment '2020年之前',
 partition p202001 values less than (202007) comment '2020年上半年',
 partition p202002 values less than (202101) comment '2020年下半年',
 partition p202101 values less than (202107)comment '2021年上半年',
 partition p202102 values less than (202201)comment '2021年下半年',
 partition p202201 values less than (202207)comment '2022年上半年',
 partition p202202 values less than (202301)comment '2022年下半年',
 partition p202301 values less than (202307)comment '2023年上半年',
 partition p202302 values less than (202401)comment '2023年下半年',
 partition p202401 values less than (202407)comment '2024年上半年',
 partition p202402 values less than (202501)comment '2024年下半年',
 partition p202501 values less than (202507)comment '2025年上半年',
 partition p202502 values less than (202601)comment '2025年下半年',
 partition p202511 values less than (maxvalue)comment '2026年及以后'
);

-- 将原数据库数据插入新的数据库
INSERT INTO `hourdb_partitioned`  (`senid`,`time`,`v`,`avgv`,`maxv`,`maxt`,`minv`,`mint`,`s`,`avgs`,`maxs`,`mins`,`span`)
select `senid`,`time`,`v`,`avgv`,`maxv`,`maxt`,`minv`,`mint`,`s`,`avgs`,`maxs`,`mins`,`span` from `hourdb` ;


-- 重命名表
rename table `hourdb` to `hourdb_backup`,`hourdb_partitioned` to `hourdb`;

-- 测试
select count(senid) from `hourdb` partition (p202401);

**注意:**在分区时,一定要按照从小到大的顺序,已经分区的内容将不再参与后续的分区。

3.2 LIST分区
sql 复制代码
CREATE TABLE `staff_partition_list` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `sex` tinyint(255) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
PARTITION BY List (id) (
	PARTITION p0 VALUES in (1,2,3,5),
	PARTITION p1 VALUES in (7,9,10),
	PARTITION p2 VALUES in (11,15)
);
3.3 HASH分区
sql 复制代码
CREATE TABLE `staff_partition_hash` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `sex` tinyint(255) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
PARTITION BY HASH (id)
PARTITIONS 3;

每次插入、更新、删除一行,hash表达式都要计算一次;这意味着非常复杂的表达式可能会引起性能问题,尤其是在执行同时影响大量行的运算(例如批量插入)的时候。

3.4 KEY分区
sql 复制代码
CREATE TABLE `staff_partition_key` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `sex` tinyint(255) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
PARTITION BY LINEAR Key (id)
PARTITIONS 3;

4.分区管理

4.1删除分区
sql 复制代码
alter table staff_partition drop partition p0;

上述语句删除p0分区,同时也会删除p0分区的数据。

sql 复制代码
 alter table staff_partition remove partitioning;

上述语句只删除p0分区,但是保留了p0分区的数据。

sql 复制代码
-- 对于hash分区和key分区
alter table staff_partition_hash COALESCE PARTITION 2;

上述命令将当前的分区数量减少到 2 个分区,数据库系统会自动选择哪些分区合并,重新分配数据

4.2增加分区

RANGE和LIST分区

sql 复制代码
alter table staff_partition add partition(partition p3 values LESS THAN (20));
  • 对于RANGE分区的表,只可以添加新的分区到分区列表的高端
  • 对于List分区的表,不能添加已经包含在现有分区值列表中的任意值

HASH和KEY分区

sql 复制代码
alter table test_staff_partition_hash add PARTITION partitions 2;
4.3重新分区
sql 复制代码
ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO 
(partition_definitions)

-- 示例
ALTER TABLE example_table
  REORGANIZE PARTITION p1 INTO (
    PARTITION p1_1 VALUES LESS THAN (100),
    PARTITION p1_2 VALUES LESS THAN (200)
  );
4.4优化分区

如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB,或TEXT类型的列)作了许多修改,可以使用ALTER TABLE ... OPTIMIZE PARTITION来收回没有使用的空间,并整理分区数据文件的碎片。

sql 复制代码
alter table test_staff_partition OPTIMIZE PARTITION p2,p3;
相关推荐
woshihuanglaoshi10 分钟前
数据迁移与版本管理 - Flutter在鸿蒙平台实现数据库升级策略
数据库·学习·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
万亿少女的梦16811 分钟前
基于Spring Boot、Java与MySQL的网络订餐系统设计与实现
java·spring boot·mysql·系统设计·网络订餐
Database_Cool_2 小时前
阿里云 RDS MySQL 降本增效实战:从规格选型到成本优化,月成本降低64%全攻略
mysql·阿里云·云计算
java_logo2 小时前
Apache Doris Docker 部署指南:实时分析数据库实战
数据库·docker·apache·doris·apache doris·轩辕镜像·docker部署doris
广州灵眸科技有限公司10 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
Cloud云卷云舒12 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
憧憬成为web高手12 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学12 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
oradh14 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
用户713335851562415 小时前
MySQL - 事务、redo/undo 日志与 MVCC
mysql