MySQL分区表(一)

MySQL分区表(一)MySQL 分区表 mysql 分区表

大家好,欢迎来到IT知识分享网。

说明:分区表,顾名思义,就是一张表根据规则,划分多个区,通过分区,实现一种“逻辑隔离”,这在Saas系统中是非常常见的。本文介绍如何在MySQL中分区。

创建分区

在MySQL中,多种分区模式,如下:

  • Range:范围分区,根据数据库表某列数值划分,像日期、数值类型的主键值;
  • List:列表分区,可选定一个集合,像group_name字段,有淘宝、天猫,按照不同的集团名分区;
  • Hash:哈希分区;
  • Key:键分区;
  • Subpartitioning:子分区;

这里介绍前面两种常见的分区,Range、List。


首先,创建两张表,用户表、集团表,如下:

CREATE TABLE `tb_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(20) DEFAULT NULL, `password` varchar(20) DEFAULT NULL, `create_date` datetime NOT NULL, PRIMARY KEY (`id`, `create_date`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT ='用户表,range分区'; 
CREATE TABLE `tb_group` ( `id` int NOT NULL AUTO_INCREMENT, `group_name` varchar(20) DEFAULT NULL, `group_code` varchar(20) NOT NULL COMMENT '集团编码', PRIMARY KEY (`id`,`group_code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='集团表,list分区'; 

需要注意

  • 创建分区表依靠的字段需要是主键或者联合主键的其中一个
  • 而且,在创建分区后,依靠分区的字段不能修改名称;

给用户表创建分区,根据创建时间(create_date)字段,如下:

-- 创建分区 alter table `tb_user` partition by range columns(create_date) ( partition tb_user_00 values less than ('2025-01-01 00:00:00'), partition tb_user_00 values less than ('2026-01-01 00:00:00')); 

这表示,创建时间在2025年内的记录为一个分区,大于2025年,小于2026年的在第二个分区。使用Range分区需要注意以下几点:

  • Range分区,严格遵循递增分区,后面分区的less than 不能小于上一个分区;
  • Range分区,数据会落在符合条件的第一个分区,如2024年的数据,会落到小于2025年的分区里,而不会落在小于2026年的分区;

创建成功,插入两条数据到用户表里;

insert into tb_user(username, password, create_date) values ('张三', '', now()), ('李四', 'abcdef', '2025-09-22 14:05:45') 

敲下面的SQL,看下分区情况:

select partition_ordinal_position, partition_method, partition_expression, partition_description, table_name, table_rows from information_schema.partitions where table_name = 'tb_user'; 

可以看到tb_user有两个分区,分区的字段,数值,以及后面两个分区各有一条记录,说明上面插入的两条记录分到了两个分区里。

(注:下面展示的是所有数据库的tb_user表的分区情况,其他数据库有重名的表,没有重名的话,应该只有两条记录)

在这里插入图片描述


再试下,List分区,这次给tb_group创建一个分区,如下:

-- 创建一个分区 alter table `tb_group` partition by list columns(group_code) ( partition tb_group_001 values in ('001')); 

表示,当记录的集团编码是001时,为一个分区,下面再添加一个002分区;

-- 添加一个分区 alter table tb_group add partition (partition tb_group_002 values in ('002')); 

需要注意

  • 创建分区和新增分区的SQL是不相同的;
  • 而新增分区的前提,是这张表需要是一张分区表;

插入数据之前,先看一下分区情况,两个分区,都没有记录;

在这里插入图片描述

插入数据

insert into tb_group(group_name, group_code) values ('总公司', '001'), ('分公司', '002'); 

再看下分区情况,可以看到两条数据被分到了不同分区;

在这里插入图片描述

如果我们插入一条数据,集团编码是003,即不在任何一个分区里面,会怎么样,如下:

在这里插入图片描述

会报错,所以需要注意

  • 没有符合条件的分区,数据会插入失败

删除分区

删除某张表的分区,用下面的SQL

alter table tb_group drop partition tb_group_001; 

表示,删除tb_group表的tb_group_001分区,需要注意,

  • 删除分区后,所处分区的数据也会被删除
  • 另外,不能删除表的所有分区,或者仅剩的一个分区

综合前面的注意点,如果根据某个字段创建分区,后续发现设计不合理,想再修改字段类型或者首个分区的范围,只好删表重建了,所以分区前要考虑清楚。

分区性能

这里创建一张有100万条记录的表,表结构如下

CREATE TABLE `test_user_1`( id INT auto_increment primary key , username VARCHAR(32), `password` VARCHAR(32), sex VARCHAR(6) ); 

用下面这个存储过程,创建一百万条记录

-- 创建存储过程 DELIMITER $$ CREATE PROCEDURE auto_insert() BEGIN DECLARE i INT DEFAULT 1; START TRANSACTION; WHILE(i<)DO INSERT INTO `test_user_1`(username, password, sex) VALUES(CONCAT('zhangsan',i) ,MD5(i), 'male'); SET i=i+1; END WHILE; COMMIT; END$$ DELIMITER ; -- 调用 CALL auto_insert(); 

在这里插入图片描述

划分为10个分区,每个分区存10万条

在这里插入图片描述

现在,来查询一条记录

select id, username, password, sex from test_user_1 where username='zhangsan'; 

1秒没到

在这里插入图片描述

现在,删除表重建,这次不建分区,再查一次,如下:

(没有分区)

在这里插入图片描述

(1秒多点)

在这里插入图片描述

老实说,我也不知道建立分区对查询有没有优化,好像是有点……大家可以创建一千万条记录试下

总结

本文介绍了MySQL分区,及创建分区时的一些注意点,汇总如下:

  • 创建分区表依靠的字段需要是主键或者联合主键中的一个;
  • 创建分区后,依靠分区的字段不能修改名称;
  • RANGE分区,严格遵循递增分区,后面分区的less than 不能小于上一个分区;
  • RANGE分区,数据会落在符合条件的第一个分区;
  • 创建分区和新增分区的SQL不同,新增分区的前提,是这张表需要是一张分区表;
  • 没有符合条件的分区,数据会插入失败
  • 删除分区后,所处分区的数据也会被删除
  • 不能删除表的所有分区,或者仅剩的一个分区

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/114122.html

(0)
上一篇 2025-12-10 18:33
下一篇 2025-12-10 19:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信