mysql分区

背景

参照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了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。

MySQL 5.1中进行分区种类

水平分区

  • Range(范围)
    这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过工资分成三个分区,1000块以内的数据,1000与2000间的数据,大于2000以上的数据。
 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 );
  • Hash(哈希)
    此种分区主要用来确保数据在预先确定数目的分区中平均分布。这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。
 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;
  • Key(键值)
    按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用户定义的表达式,而KEY分区的哈希函数是由MySQL 服务器提供,服务器使用其自己内部的哈希函数,这些函数是基于与PASSWORD()一样的运算法则。“CREATE TABLE …PARTITION BY KEY”的语法规则类似于创建一个通过HASH分区的表的规则。它们唯一的区别在于使用的关键字是KEY而不是HASH,并且KEY分区只采用一个或多个列名的一个列表。
 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;
  • List(预定义列表)
    这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA建立了一个横跨三个分区的表,分别根据2004年2005年和2006年值所对应的数据。
 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) );
  • Composite(复合模式)
    这种模式允许分区之后在分区,举例:在初始化已经进行了Range范围分区的表上,我们可以对其中一个分区再进行hash哈希分区。

垂直分区

分区表的操作

  • 删除分区
 #一次删除一个分区
 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程序也告诉我们在对已分区的表的查询过程中仅对第一个分区进行了扫描,其他都跳过了

你可能感兴趣的:(mysql,数据库)