mysql分区的分区,简单来说是将一个表根据指定的条件,水平切分.
将一张物理表,切为多个物理表,但在数据库表现上还是一张表.
这样的好处是, 当查询条件可以判定到某张分区表的时候,会只查询这张分区表,而不用整表扫描.
值得注意的是,有外键关联的表不能进行分区. 直到现在这个情况也没有改变. 当前mysql最新版本为5.5.
一. 查看数据库是否支持分区
1
|
SHOW VARIABLES
LIKE
'%partition%'
;
|
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| have_partition_engine | YES |
+-----------------------+-------+
1 row in set (0.00 sec)
二. 创建分区
分区目前有4个类型 RANGE, LIST, HASH, KEY, 这篇博客要讲的是RANGE类型. 手册里如下描述.
1
|
RANGE : 基于属于一个给定连续区间的列值,把多行分配给分区。
|
注意:RANGE的值只能从小到大,而且,标识列必须包含在主键里.
创建range分区有2种方式,1种是创建表时就创建分区,另1种是创建表后再创建分区.
1.创建表时就创建分区
1
2
3
4
5
6
7
8
9
10
11
12
|
CREATE
TABLE
members (
id
INT
,
fname
VARCHAR
(25),
entry_time DATETIME,
PRIMARY
KEY
(`id`,`entry_time`)
)
PARTITION
BY
RANGE(entry_time) (
PARTITION p0
VALUES
LESS THAN (
'2013-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p1
VALUES
LESS THAN (
'2013-12-31 23:59:59'
) ENGINE = InnoDB,
PARTITION p2
VALUES
LESS THAN (
'2014-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p3
VALUES
LESS THAN (MAXVALUE) ENGINE = InnoDB
);
|
2.创建表后再创建分区
1
2
3
4
5
6
|
ALTER
TABLE
members PARTITION
BY
RANGE(entry_time) (
PARTITION p0
VALUES
LESS THAN (
'2013-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p1
VALUES
LESS THAN (
'2013-12-31 23:59:59'
) ENGINE = InnoDB,
PARTITION p2
VALUES
LESS THAN (
'2014-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p3
VALUES
LESS THAN (MAXVALUE) ENGINE = InnoDB
);
|
分区后, Mysql 将会 members 分成 4个表, 将 '2013-06-30 23:59:59' 以前注册的都放在p0里, 将 '2013-12-31 23:59:59'以前注册的都放在p1里,以此类推,
2014年7月份和以后的都放在p3里.
三. 测试分区
使用 explain partitions 测试查询语句是否精确到单个分区.
1
2
3
4
5
6
7
8
|
explain partitions
select
count
(*)
from
members
where
entry_time =
'2013-03-01 23:59:59'
;
+
----+-------------+--------+------------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type |
table
| partitions | type | possible_keys |
key
| key_len | ref |
rows
| Extra |
+
----+-------------+--------+------------+-------+---------------+-----------+---------+------+------+--------------------------+
| 1 | SIMPLE | school | p0 |
index
|
PRIMARY
| id | 8 |
NULL
| 2 | Using
where
; Using
index
|
+
----+-------------+--------+------------+-------+---------------+-----------+---------+------+------+--------------------------+
1 row
in
set
(0.00 sec)
|
四. 获取分区信息
1
|
mysql> SHOW
CREATE
TABLE
members\G
|
显示如下
1
2
3
4
5
6
7
8
9
10
11
|
CREATE
TABLE
members (
id
INT
,
fname
VARCHAR
(25),
entry_time DATETIME
)
PARTITION
BY
RANGE(entry_time) (
PARTITION p0
VALUES
LESS THAN (
'2013-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p1
VALUES
LESS THAN (
'2013-12-31 23:59:59'
) ENGINE = InnoDB,
PARTITION p2
VALUES
LESS THAN (
'2014-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p3
VALUES
LESS THAN (MAXVALUE) ENGINE = InnoDB
);
|
五. 修改分区(拆分,合并)
拆分
上边 member 的分区,只分到了2014年6月份.现在我们将p3分区重拆分为多个分区.
1
2
3
4
5
6
7
|
ALTER
TABLE
members REORGANIZE PARTITION p3
INTO
(
PARTITION p4
VALUES
LESS THAN (
'2014-12-31 23:59:59'
) ENGINE = InnoDB,
PARTITION p5
VALUES
LESS THAN (
'2015-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p6
VALUES
LESS THAN (
'2015-12-31 23:59:59'
) ENGINE = InnoDB,
PARTITION p7
VALUES
LESS THAN (
'2016-06-30 23:59:59'
) ENGINE = InnoDB,
PARTITION p8
VALUES
LESS THAN (MAXVALUE) ENGINE = InnoDB
);
|
合并
再次声明:RANGE的值只能从小到大,而且,标识列必须包含在主键里.
现在将p0,p1,p2合并到m1里.
1
2
3
|
ALTER
TABLE
members REORGANIZE PARTITION p0,p1,p2
INTO
(
PARTITION m1
VALUES
LESS THAN (
'2014-06-31 23:59:59'
) ENGINE = InnoDB
);
|
六. 重新分区
语法与创建分区一样, 直接 alter by 就可以了.Mysql会将旧分区逻辑删除掉.
比如更改分区 标志列.
1
2
3
4
5
6
|
ALTER
TABLE
members PARTITION
BY
RANGE(id) (
PARTITION p0
VALUES
LESS THAN (10000) ENGINE = InnoDB,
PARTITION p1
VALUES
LESS THAN (20000) ENGINE = InnoDB,
PARTITION p2
VALUES
LESS THAN (30000) ENGINE = InnoDB,
PARTITION p3
VALUES
LESS THAN (MAXVALUE) ENGINE = InnoDB
);
|
还可以更改为其他分区类型 如 LIST,HASH等. 举一个HASH的例子, 将id平均分布到5分区表.
1
|
ALTER
TABLE
members PARTITION
BY
HASH (id) PARTITIONs 5;
|
七. 删除分区以及分区数据
如非必要,尽量不要用,使用 拆分合并更好一点.
1
|
ALTER
TABLE
tr
DROP
PARTITION p1;
|