在阐述MySQL分区时,我们需要先来了解一下分区的概念是什么,它的优势在哪里,是如何区分类型的。
1.分区概述
在MySQL中,InnoDB存储引擎长期支持表空间的概念,并且MySQL服务器甚至在分区引入之前,就能配置为存储不同的数据库使用不同的物理路径。分区(partion)更进一步,它允许你通过设置各种规则将一个表的各个分区跨文件系统存储。实际上,不同位置的不同表分区是作为一个单独的表来存储的。用户所选择的、实现数据分割的规则被称为分区函数(partioning function),这在MySQL中它可以是模数,或者是简单的匹配一个连续的数值区间或数值列表,或者是一个内部HASH函数,或一个线性HASH函数。
最常见是的水平分区(horizontal partitioning),也就是将表的不同的元组分配到不同的物理分区上。目前,MySQL 5.1还不支持垂直分区(vertical partitioning),即将表的不同列分配到不同的物理分区。你可以使用MySQL支持的大多数存储引擎来创建表的分区,在MySQL 5.1中,同一个表的各个分区必须使用相同的存储引擎,比如,你不能对一个分区使用MyISAM,而对另一个分区使用InnoDB。但是,你可以对同一个数据库的不同的表使用不同的存储引擎。
举一个HASH分区的例子 -- 创建一个通过HASH分成6个分区、使用InnoDB存储引擎的表:
CREATE TABLE ti (
id INT UNSIGNED ,
tr_date date
)ENGINE=INNODB PARTITION BY HASH(MONTH(tr_date)) PARTITIONS 6 ;
注意:分区必须对一个表的所有数据和索引;不能只对数据分区而不对索引分区,反之亦然,同时也不能只对表的一部分进行分区
2. MySQL分区的优势:
2.1> 与单个磁盘或文件系统分区相比,单个表可以存储更多的数据
2.2> 对于那些已经失去保存意义的数据,通常可以通过删除与那些数据有关的分区,很容易地删除那些数 据。相反地,在某些情况下,添加新数据的过程又可以通过为那些新数据专门增加一个新的分区,来 很方便地实现。
2.3> 对于带Where的条件查询语句,可以得到更大的优化;只需要查询某些分区,而不用扫描全部分区
2.4> 一些聚合函数,比如SUM() 和COUNT(),能够很容易的并行执行
3. 分区类型
3.1> RANGE分区(portioning):根据列值所属的范围区间,将元组分配到各个分区
LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进 行选 择
3.2> HASH分区:根据用户定义的函数的返回值来进行选择的分区,该表达式使用将要插入到表中的这些 行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。
3.3> KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL 服务器提供其 自身的哈希函数。
4. 下面一起进入实例中加深印象吧!
范围分区实例:
4.1 > 创建分区表 part_tab
CREATE TABLE part_tab (
c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=INNODB 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 ) ;
在Navicate中执行(如图):
4.2> 创建一个不分区的表(no_part_tab)
create table no_part_tab (
c1 int(11) default NULL ,
c2 varchar(30) default NULL,
c3 date default NULL
) engine = INNODB ;
4.3> 创建一个生成800万行数据的存储过程:
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
如图:
4.4> 调用存储过程,执行如下代码:
delimiter ;
call load_part_tab();
如图:
4.5> 为 不分区表 no_part_tab 导入数据(数据与分区表part_tab一致)
insert into no_part_tab select * from part_tab;
5. 数据都准备好了, 开始测试
5.1> 查询不分区表
select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31';
执行效果:
5.2 > 查询分区表
select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31';
执行效果:
5.3> 使用EXPLAIN 进行对比
5.3.1> EXPLAIN PARTITIONS SELECT COUNT(*) FROM part_tab where
c3 > date '1995-01-01' and c3 < date '1995-12-31' ;
5.3.2> EXPLAIN SELECT COUNT(*) FROM no_part_tab WHERE c3 > date '1995-01-01' and c3 < date '1995-12-31' ;
可以看到,分区和未分区占用文件空间大致相同 (数据和索引文件)
如果查询语句中有未建立索引的字段,分区时间远远优于未分区时间
如果查询语句中字段建立了索引,分区和未分区的差别缩小,分区略优于未分区
网友评论