mysql分区表

1、       mysql分区简介

数据库分区mysql

数据库分区是一种物理数据库设计技术。虽然分区技术能够实现不少效果,但其主要目的是为了在特定的SQL操做中减小数据读写的总量以缩减sql语句的响应时间,同时对于应用来讲分区彻底是透明的。算法

MYSQL的分区主要有两种形式:水平分区和垂直分区sql

 

水平分区(HorizontalPartitioning)数据库

这种形式的分区是对根据表的行进行分区,经过这样的方式不一样分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。
全部在表中定义的列在每一个数据集中都能找到,因此表的特性依然得以保持。水平分区必定要经过某个属性列来分割。常见的好比年份,日期等。express

 

垂直分区(VerticalPartitioning)服务器

这种分区方式通常来讲是经过对表的垂直划分来减小目标表的宽度,使某些特定的列被划分到特定的分区,每一个分区都包含了其中的列所对应全部行。
能够用  showvariables like '%partition%';mysql优化

命令查询当前的mysql数据库版本是否支持分区。less

分区的做用:数据库性能的提高和简化数据管理数据库设计

在扫描操做中,mysql优化器只扫描保护数据的那个分区以减小扫描范围得到性能的提升。ide

分区技术使得数据管理变得简单,删除某个分区不会对另外的分区形成影响,分区有系统直接管理不用手工干预。

mysql从5.1版本开始支持分区。每一个分区的名称是不区分大小写。同个表中的分区表名称要惟一。

2、       mysql分区类型

根据所使用的不一样分区规则能够分红几大分区类型。

RANGE 分区:

基于属于一个给定连续区间的列值,把多行分配给分区。 

LIST 分区:

相似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

HASH分区:

基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数能够包含MySQL中有效的、产生非负整数值的任何表达式。

KEY
分区:相似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

复合分区:

基于RANGE/LIST 类型的分区表中每一个分区的再次分割。子分区能够是 HASH/KEY 等类型。

 

3、       mysql分区表经常使用操做示例

以部门员工表为例子: 

1)       建立range分区

 

createtable emp

(empno varchar(20notnull ,

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

);

以员工工资为依据作范围分区。

 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate date notnull,

salary int

)

partition by range(year(birthdate))

(

partition p1 values less than (1980),

partition p2 values less than (1990),

partition p3 values less than maxvalue

);

year(birthdate)表达式(计算员工的出生日期)做为范围分区依据。这里最值得注意的是表达式必须有返回值。

 

2)       建立list分区

 

createtable emp

(empno  varchar(20notnull ,

empname varchar(20),

deptno  int,

birthdate datenotnull,

salary int

)

partition by list(deptno)

(

partition p1 valuesin  (10),

partition p2 valuesin  (20),

partition p3 valuesin  (30)

);

以部门做为分区依据,每一个部门作一分区。

 

3)       建立hash分区

HASH分区主要用来确保数据在预先肯定数目的分区中平均分布。在RANGE和LIST分区中,必须明确指定一个给定的列值或列值集合应该保存在哪一个分区中;而在HASH分区中,MySQL 自动完成这些工做,你所要作的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition by hash(year(birthdate))

partitions 4;

4)       建立key分区

按照KEY进行分区相似于按照HASH分区,除了HASH分区使用的用户定义的表达式,而KEY分区的哈希函数是由MySQL 服务器提供,服务器使用其本身内部的哈希函数,这些函数是基于与PASSWORD()同样的运算法则。“CREATE TABLE ...PARTITION BY KEY”的语法规则相似于建立一个经过HASH分区的表的规则。它们惟一的区别在于使用的关键字是KEY而不是HASH,而且KEY分区只采用一个或多个列名的一个列表。 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition bykey(birthdate)

partitions 4;

 

 

5)       建立复合分区

 

range - hash(范围哈希)复合分区

 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition by range(salary)

subpartition by hash(year(birthdate))

subpartitions 3

(

partition p1 values less than (2000),

partition p2 values less than maxvalue

);

range- key复合分区

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition by range(salary)

subpartition bykey(birthdate)

subpartitions 3

(

partition p1 values less than (2000),

partition p2 values less than maxvalue

);

list - hash复合分区

CREATETABLE emp (

empno varchar(20NOTNULL,

empname varchar(20) ,

deptno int,

birthdate dateNOTNULL,

salary int

)

PARTITION BY list (deptno)

subpartition by hash(year(birthdate))

subpartitions 3

(

PARTITION p1 VALUESin  (10),

PARTITION p2 VALUESin  (20)

)

;

list - key 复合分区

 

CREATETABLE empk (

empno varchar(20NOTNULL,

empname varchar(20) ,

deptno int,

birthdate dateNOTNULL,

salary int

)

PARTITION BY list (deptno)

subpartition bykey(birthdate)

subpartitions 3

(

PARTITION p1 VALUESin  (10),

PARTITION p2 VALUESin  (20)

)

;

6)       分区表的管理操做

删除分区:

altertable emp drop partition p1;

不能够删除hash或者key分区。

一次性删除多个分区,altertable emp drop partition p1,p2;

增长分区:

altertable emp add partition (partition p3 values less than (4000));

altertable empl add partition (partition p3 valuesin (40));

分解分区:

Reorganizepartition关键字能够对表的部分分区或所有分区进行修改,而且不会丢失数据。分解先后分区的总体范围应该一致。

altertable te

reorganize partition p1 into

(

partition p1 values less than (100),

partition p3 values less than (1000)

); ----不会丢失数据

合并分区:

Merge分区:把2个分区合并为一个。
altertable te

reorganize partition p1,p3 into

(partition p1 values less than (1000));

----不会丢失数据

 

从新定义hash分区表:

Altertable emp partition by hash(salary)partitions 7;

----不会丢失数据

从新定义range分区表:

Altertable emp partitionbyrange(salary) 

(

partition p1 values less than (2000),

partition p2 values less than (4000)

); ----不会丢失数据

 

删除表的全部分区:


Altertable emp removepartitioning;--不会丢失数据

 

重建分区:

这和先删除保存在分区中的全部记录,而后从新插入它们,具备一样的效果。它可用于整理分区碎片。 

ALTERTABLE emp rebuild partitionp1,p2;

优化分区:

若是从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB,或TEXT类型的列)做了许多修改,可使用“ALTER TABLE ... OPTIMIZE PARTITION”来收回没有使用的空间,并整理分区数据文件的碎片。 

ALTERTABLE emp optimize partition p1,p2;

分析分区:

读取并保存分区的键分布。

ALTERTABLE emp analyze partition p1,p2;

 

修补分区:

修补被破坏的分区。 

ALTERTABLE emp repairpartition p1,p2;

 

检查分区:

可使用几乎与对非分区表使用CHECK TABLE 相同的方式检查分区。

ALTERTABLE emp CHECK partition p1,p2;

这个命令能够告诉你表emp的分区p1,p2中的数据或索引是否已经被破坏。若是发生了这种状况,使用“ALTER TABLE ... REPAIR PARTITION”来修补该分区。 

 

 

【mysql分区表的局限性】

1.      在5.1版本中分区表对惟一约束有明确的规定,每个惟一约束必须包含在分区表的分区键(也包括主键约束)。

 

CREATETABLE emptt (

empno varchar(20NOTNULL  ,

empname varchar(20),

deptno int,

birthdate dateNOTNULL,

salary int ,

primarykey (empno)

)

PARTITION BY range (salary)

(

PARTITION p1 VALUES less than (100),

PARTITION p2 VALUES less than (200)

);

这样的语句会报错。MySQL Database Error: A PRIMARY KEY must include allcolumns in the table's partitioning function;

CREATETABLE emptt (

empno varchar(20NOTNULL  ,

empname varchar(20) ,

deptno int(11),

birthdate dateNOTNULL,

salary int(11) ,

primarykey (empno,salary)

)

PARTITION BY range (salary)

(

PARTITION p1 VALUES less than (100),

PARTITION p2 VALUES less than (200)

);

在主键中加入salary列就正常。

 

2.      MySQL分区处理NULL值的方式

若是分区键所在列没有notnull约束。

若是是range分区表,那么null行将被保存在范围最小的分区。

若是是list分区表,那么null行将被保存到list为0的分区。

在按HASH和KEY分区的状况下,任何产生NULL值的表达式mysql都视同它的返回值为0。

为了不这种状况的产生,建议分区键设置成NOT NULL。

 

3.      分区键必须是INT类型,或者经过表达式返回INT类型,能够为NULL。惟一的例外是当分

区类型为KEY分区的时候,可使用其余类型的列做为分区键( BLOB or TEXT 列除外)。

 

4.      对分区表的分区键建立索引,那么这个索引也将被分区,分区键没有全局索引一说。

5.      只有RANG和LIST分区能进行子分区,HASH和KEY分区不能进行子分区。

6.      临时表不能被分区。

 

4、       获取mysql分区表信息的几种方法

1.     show create table 表名
能够查看建立分区表的create语句 

2.     show table status 
能够查看表是否是分区表 

3.     查看information_schema.partitions表 
select 
  partition_name part,  
  partition_expression expr,  
  partition_description descr,  
  table_rows  
from information_schema.partitions  where 
  table_schema = schema()  
  and table_name='test';  
能够查看表具备哪几个分区、分区的方法、分区中数据的记录数等信息 

4.     explain partitions select语句
经过此语句来显示扫描哪些分区,及他们是如何使用的.

 

5、       分区表性能比较

1.     建立两张表: part_tab(分区表),no_part_tab(普通表)

CREATE TABLEpart_tab 

( c1 int defaultNULL, c2 varchar2(30) default NULL, c3 date not null) 

PARTITION BYRANGE(year(c3)) 

(PARTITION p0VALUES LESS THAN (1995),

PARTITION p1 VALUESLESS THAN (1996) , 

PARTITION p2 VALUESLESS THAN (1997) ,

PARTITION p3 VALUESLESS THAN (1998) ,

 PARTITION p4 VALUES LESS THAN (1999) ,

PARTITION p5 VALUESLESS THAN (2000) , 

PARTITION p6 VALUESLESS THAN (2001) ,

PARTITION p7 VALUESLESS THAN (2002) , 

PARTITION p8 VALUESLESS THAN (2003) ,

PARTITION p9 VALUESLESS THAN (2004) , 

PARTITION p10VALUES LESS THAN (2010),

PARTITION p11VALUES LESS THAN (MAXVALUE) );

CREATE TABLE no_part_tab

( c1 int defaultNULL, c2 varchar2(30) default NULL, c3 date not null);

 

2.     用存储过程插入800万条数据

CREATE PROCEDUREload_part_tab()

    begin

    declare v int default 0;

    while v < 8000000

    do

        insert into part_tab

        values (v,'testingpartitions',adddate('1995-01-01',(rand(v)*36520)mod 3652));

         set v = v + 1;

    end while;

end;

insert into no_part_tab  select * frompart_tab;

3.     测试sql性能

查询分区表:

selectcount(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----------+
| count(*) |
+----------+
|   795181 |
+----------+
1 row in set (2.62 sec)

查询普通表:

selectcount(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----------+
| count(*) |
+----------+
|   795181 |
+----------+
1 row in set (7.33 sec)

分区表的执行时间比普通表少70%。

 

4.     经过explain语句来分析执行状况

mysql>explain select count(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+

| id |select_type | table    | type |possible_keys | key  | key_len | ref  | rows   | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+

|  1 | SIMPLE      | part_tab | ALL  | NULL          | NULL | NULL    | NULL | 7980796 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+

1 rowin set

 

mysql>explain select count(*) from no_part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----+-------------+-------------+------+---------------+------+---------+------+---------+-------------+

| id |select_type | table       | type |possible_keys | key  | key_len | ref  | rows   | Extra       |

+----+-------------+-------------+------+---------------+------+---------+------+---------+-------------+

|  1 | SIMPLE      | no_part_tab | ALL  | NULL          | NULL | NULL    | NULL | 8000206 | Using where |

+----+-------------+-------------+------+---------------+------+---------+------+---------+-------------+

1 rowin set

mysql >

分区表执行扫描了7980796行,而普通表则扫描了8000206行。

相关文章
相关标签/搜索