参照http://blog.csdn.net/pzw_0612/article/details/45441549
分表存在需要对应用的不透明。
数据库分区是一种物理数据库设计技术,主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。
分区主要有两种形式://这里一定要注意行和列的概念(row是行,column是列)
1. 水平分区(Horizontal Partitioning) 这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。
举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。
2. 垂直分区(Vertical Partitioning) 这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。
举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。
create table emp ( empno varchar(20) not null , empname varchar(20), deptno int, birthdate date, salary int ) partition by range(salary) ( partition p1 values less than (1000), partition p2 values less than (2000), partition p3 values less than maxvalue );
create table emp ( empno varchar(20) not null , empname varchar(20), deptno int, birthdate date not null, salary int ) partition by hash(year(birthdate)) partitions 4;
create table emp ( empno varchar(20) not null , empname varchar(20), deptno int, birthdate date not null, salary int ) partition by key(birthdate) partitions 4;
create table emp ( empno varchar(20) not null , empname varchar(20), deptno int, birthdate date not null, salary int ) partition by list(deptno) ( partition p1 values in (10), partition p2 values in (20), partition p3 values in (30) );
略
略
#一次删除一个分区
alter table emp drop partition p1;
#一次性删除多个分区,
alter table emp drop partition p1,p2;
不可以删除hash或者key分区。
alter table emp add partition (partition p3 values less than (4000));
alter table empl add partition (partition p3 values in (40));
Reorganizepartition关键字可以对表的部分分区或全部分区进行修改,并且不会丢失数据。分解前后分区的整体范围应该一致
alter table te reorganize partition p1 into ( partition p1 values less than (100), partition p3 values less than (1000) );
不会丢失数据
Merge分区:把2个分区合并为一个
Merge分区:把2个分区合并为一个。 alter table te reorganize partition p1,p3 into (partition p1 values less than (1000));
不会丢失数据
本人电脑配置:
cpu:i7 8核
内存:8G
--分区表
CREATE TABLE part_tab
( c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=myisam
PARTITION BY RANGE (year(c3))
(
PARTITION p0 VALUES LESS THAN (1995),
PARTITION p1 VALUES LESS THAN (1996) ,
PARTITION p2 VALUES LESS THAN (1997) ,
PARTITION p3 VALUES LESS THAN (1998) ,
PARTITION p4 VALUES LESS THAN (1999) ,
PARTITION p5 VALUES LESS THAN (2000) ,
PARTITION p6 VALUES LESS THAN (2001) ,
PARTITION p7 VALUES LESS THAN (2002) ,
PARTITION p8 VALUES LESS THAN (2003) ,
PARTITION p9 VALUES LESS THAN (2004) ,
PARTITION p10 VALUES LESS THAN (2010),
PARTITION p11 VALUES LESS THAN MAXVALUE
);
--不分区表
create table no_part_tab
(c1 int(11) default NULL,
c2 varchar(30) default NULL,
c3 date default NULL) engine=myisam;
--分区插入存储过程定义
DELIMITER //
CREATE PROCEDURE load_part_tab() begin declare v int default 0;
while v < 8000000
do
insert into part_tab
values (v,'testing partitions',adddate('1995-01-01',(rand(v)*36520) mod 3652));
set v = v + 1;
end while;
end
//
--非分区插入存储过程定义
DELIMITER //
CREATE PROCEDURE load_no_part_tab() begin declare v int default 0;
while v < 8000000
do
insert into no_part_tab
values (v,'testing partitions',adddate('1995-01-01',(rand(v)*36520) mod 3652));
set v = v + 1;
end while;
end
//
mysql> delimiter ; mysql> call load_part_tab();
Query OK, 1 row affected (2 min 56.90 sec)
delimiter ;
call load_no_part_tab();
Query OK, 1 row affected (2 min 8.92 sec)
插入操作,性能相差无几,分区插入略慢
# 分区
mysql> select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'; +----------+
| count(*) | +----------+
| 795181 | +----------+
1 row in set (0.20 sec)
# 不分区
mysql> select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'; +----------+
| count(*) | +----------+
| 795181 | +----------+
1 row in set (1.88 sec)
# 分区
mysql> explain select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: part_tab
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 798458
Extra: Using where
1 row in set (0.00 sec)
# 不分区
mysql> explain select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: no_part_tab
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 8000000
Extra: Using where
1 row in set (0.00 sec)
小结
设计恰当表分区能比非分区的减少90%的响应时间。而命令解析Explain程序也告诉我们在对已分区的表的查询过程中仅对第一个分区进行了扫描,其他都跳过了