最近在做订单历史数据的迁移,由于订单表数据量太大,再加上这些历史数据还要被查询,为了提高查询速度,对历史表进行了分区,做 了一些了解。简单来说表分区就是能够通过一定规则把表的不同部分在不同的位置存储为单独的表,这个分割表数据的规则叫做分区函数,在mysql中可以是求 余,也可以是一个数值区间,还可以是线性的hash函数,如果还记得数据结构中的hash函数处理key冲突时所用的方法,那么对这个就不陌生了。分区函数根据用户提供的参数,计算出记录所在的分区。
分区的优点:
1.可以把分区建立在多个磁盘上,这样相比单个文件系统或者单个磁盘,可以存储更多数据。(这个还可以通过分库分表,这样也能更好的满足业务需求)也便于管理。
2.一些查询可以等到极大的优化,如果条件的数据只保存在一个分区内,那么在查找数据的时候,只需要在这个分区内查找,能够快速定位到记录。
3.如果分区分布在不同的磁盘上,可以同步查询数据,这样可以获取更大的吞吐量。涉级聚合函数时候,可以很容易的进行并行处理。
mysql 分区主要有以下几个类型:
1.range分区
基于一个给定的连续区间的列值,通过分区函数分配到各自分区,
语法:partition range by(expr)
create table foo(
id int not null,
fname VARCHAR(20),
created Date NOT NULL,
modified Date NOT NULL,
PRIMARY KEY (id)
)COMMENT='foo 表分区 使用range方式'
PARTITION by range(id)(
PARTITION P0 VALUES LESS TAN (100), #P0为分区名字 必须唯一的
PARTITION P1 VALUES LESS THAN (200),
PARTITION P2 VALUES LESS THAN (300)
)
上面小于100的记录都在分区P0中,而100-200的记录在P2中,以此类推,每个分区都是按顺序定义的,从最低到最高,类似java中的switch..case,如果id大于300那么库就不知道保存在什么地方了。这时候可以指定最 大值,如下:
create table foo(
id int not null,
fname VARCHAR(20),
created Date NOT NULL,
modified Date NOT NULL,
PRIMARY KEY (id)
)COMMENT='foo 表分区 使用range方式'
PARTITION by range(id)(
PARTITION P0 VALUES LESS THAN (100), #P0为分区名字 必须唯一的
PARTITION P1 VALUES LESS THAN (200),
PARTITION P2 VALUES LESS THAN (300),
PARTITION P3 VALUES LESS THAN MAXVALUE #指定了最大值
)
从错误中可以看出,分区key必须有PRIMARY KEY里的字段,而这次使用的是created字段,按年分区, 并没有包含在primary key,所以报错
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
如果一个表没有唯一键,或者主键,那么使用分区key就没有这个限制,这是时候可以使用任何key,如果表有主键那么分区使用的key必须是包含在primary key中,可以使用联合主键来解决这个冲突
create table foo(
id int not null,
fname VARCHAR(20),
created Date NOT NULL,
modified Date NOT NULL,
PRIMARY KEY (id,created) #这次加上了 created联合主键 这时候创建分区能够成功的
)COMMENT='foo 表分区 使用range方式'
PARTITION by range(YEAR(created))(
PARTITION P0 VALUES LESS THAN (2011), #P0为分区名字 必须唯一的
PARTITION P1 VALUES LESS THAN (2012),
PARTITION P2 VALUES LESS THAN (2013),
PARTITION P3 VALUES LESS THAN MAXVALUE
)
这样是能够成功的,同样的问题在接下的几种分区方式中也会存在。
2.list分区,
这种类型的分区,主要针对某些列的值从属一个列表的中的一个值,而range是从属一个连续区间的集合。
语法:partition by list(expr)
创建一个list分区表:
部门 |
团队编号teamId |
研发部 |
1,2,7 |
财务部 |
3,5,8 |
营销部 |
4,6,9,10 |
create table foo(
id int not null,
fname VARCHAR(20),
teamId int not null,
created Date NOT NULL,
modified Date NOT NULL
)COMMENT='foo 表分区 使用LIST方式'
PARTITION by LIST(teamId)(
PARTITION P0 VALUES IN (1,2,7), #P0为分区名字 必须唯一的
PARTITION P1 VALUES IN (3,5,8),
PARTITION P2 VALUES IN (4,6,9,10)
)
正如之前说所说的,表不存在主键的情况下,我们可以使用任何字段作为分区key,执行成功,
3.hash分区
hash分区是让记录在确定数目的分区中平均分布,可以看到在list,和range分区方式中是需要明确指定给定列值保存的分区,而在hash分区中,mysql自动分配记录所在的分区。
语法:partition by hash(expr) expr可以是任何表达式
创建一个订单表demo
create table order_table(
order_id int not null,
created Date NOT NULL,
modified Date NOT NULL,
PRIMARY KEY (order_id)
)COMMENT='foo 表分区 使用hash方式'
PARTITION BY HASH(order_id)
PARTITIONS 10 #定义分区数
执行结果
该表被分成了10个分区,这里如果PARTITIONS 10不写,默认的分区数量就是1。如果分区函数符合y=nx,那么这种就越适合hash分区,可以理解数据在各个分区上会很均匀,确定分区实际上就是MOD(expr,num)其中 num为分区数。这是很普通的hash分区。
LINEAR HASH分区
LINEAR HASH和HASH分区类似,语法上有一点区别,partition by linear hash(expr),确定分区上使用的:POWER(2.CELING(LOG(2,NUM)))
4.key分区
key分区和hash分区类似,只是分区函数由mysql提供。
语法:partition by key(expr)
create table order_table(
order_id int not null,
created Date NOT NULL,
modified Date NOT NULL,
PRIMARY KEY (order_id)
)COMMENT='foo 表分区 使用hash方式'
PARTITION BY KEY(order_id)
PARTITIONS 10 #定义分区数
5.子分区
子分区是对每个分区进行再次分割,
这次我是用的是按年分区,然后年下面按月分子分区。range加hash分区方式
CREATE TABLE order_table (
order_id bigint NOT NULL DEFAULT 0,
created datetime NOT NULL COMMENT '创建时间',
#中间省掉了很多字段
modified datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (order_id,created)
) COMMENT='订单表 创建子分区 range hash'
PARTITION BY RANGE(YEAR(created))
SUBPARTITION BY HASH(MONTH(created))
#按月分区
SUBPARTITIONS 12
(
PARTITION P11 VALUES LESS THAN (2011),
PARTITION p12 VALUES LESS THAN (2012),
PARTITION P13 VALUES LESS THAN (2013),
PARTITION P14 VALUES LESS THAN (2014),
PARTITION p15 VALUES LESS THAN (2015),
PARTITION P16 VALUES LESS THAN (2016),
PARTITION P17 VALUES LESS THAN (2017),
PARTITION p18 VALUES LESS THAN (2018),
PARTITION p19 VALUES LESS THAN MAXVALUE
)
创建成功。这里直接只指定数量,让mysql去找相应的分区,当然也可以直接定义子分区。也可以指定数据存储节点和索引存储节点,由于项目需要就纪录下。
参考文档:
http://dev.mysql.com/doc/refman/5.1/zh/partitioning.html
http://dev.mysql.com/doc/refman/5.1/en/partitioning-limitations-partitioning-keys-unique-keys.html
相关推荐
3. **添加数据**:向分区表中插入数据,MySQL会自动根据分区规则分配。 4. **管理分区**:可以添加、删除或重定义分区,以适应数据变化。 **示例:RANGE分区创建** ```sql CREATE TABLE p_range ( id INT(10) NOT...
- 在分区表的上下文中,触发器可能用于在数据插入或更新时自动调整分区,确保数据分布合理。 7. **维护与备份**: - 分区使得大型表的备份和恢复更加高效,因为可以分别处理每个分区,而非整个表。 - 数据迁移和...
详细介绍MYSQL表分区的原理及步骤!什么是数据库分区? 数据库分区是一种物理数据库设计技术,DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的...
MySQL分区表是一种优化大型数据表查询效率的技术,它将一个大表分成多个逻辑上相连但物理上独立的部分,每个部分称为一个分区。分区可以按照不同的策略进行,如范围、哈希、列表或复合分区。这样做有助于提高数据...
### SQL Server 2005新特性之表分区的功能 #### 一、引言 随着企业数据量的不断增加,数据库管理系统的性能优化变得尤为重要。为了应对海量数据带来的挑战,SQL Server 2005引入了表分区功能。通过将表中的数据...
MySQL 5.5.8 版本在数据库领域是一个重要的里程碑,它引入了许多性能改进和新特性,尤其是在分区表方面。分区表是大型数据库系统中优化查询性能的一种策略,通过将大表的数据逻辑上划分为更小、更易管理的部分。在...
实现mysql 每天定时自动给数据库表追加分区,包含存储计划和存储过程
mysql5.1开始支持数据表分区了。如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区。当然也可根据其他的条件分区。二、为什么要对表进行分区为了改善大型表以及具有各种...
#### 三、MySQL分区表常用操作示例 接下来通过具体的示例来展示如何创建不同类型的分区表: 1. **创建RANGE分区**: - 基于员工工资创建范围分区:`CREATE TABLE emp (empno VARCHAR(20) NOT NULL, empname ...
首先,我们需要理解MySQL分区的概念。分区是将一个大表逻辑上划分为多个较小的部分,每个部分称为一个分区。对于时间序列数据,如日志记录,根据日期或时间进行分区可以显著提高查询速度,因为查询通常针对特定时间...
"互联网公司为啥不使用mysql分区表" 在互联网公司中,mysql分区表是一个比较少用的技术,这是因为分区表存在一些缺陷和限制,使得互联网公司更多地选择自己分库分表来水平扩展数据库。 首先,分区表的设计需要考虑...
MySQL分区是一种数据库优化技术,它将大型表分成更小、更易管理的部分,每个部分称为一个分区。这种技术有助于提高查询性能,特别是对于那些需要处理大量数据或执行复杂查询的应用程序。MySQL支持多种分区类型,包括...
【MySQL分区表详解】 分区表是数据库管理中一种高级的数据组织策略,主要目的是为了提高大表的查询效率和数据管理的便利性。在MySQL中,分区表是通过`PARTITION BY`子句来实现的,它允许我们将一个大的表根据特定的...
一共10套教程。深入浅出MySQL生产环境高可用架构MyCat教程 尚硅谷Redis视频 高性能mysql优化 打造扛得住的MySQL数据库架构(5.7 阿里大神讲授MySQL数据库运维...MySQL表分区管理 MYSQL运维DBA实战(5.5,一般,不推荐了)