分区和性能


数据库的应用分为两类:
1、OLTP 在线事务处理,如blog,电子商务,网络游戏
2、OLAP 在线分析处理,如数据仓库,数据集市
3、对于OLAP的应用,分区的确是可以很好地提高查询的性能,因为OLAP应用大多数查询需要频繁地扫描一张很大的表。假设有一张1亿行的表,其中有一个时间戳属性列,用户查询需要从这张表中获取一年的数据,如果按时间进行分区,则只需要扫描相应的分区即可。
4、但是对于OLTP的应用,分区应该非常小心,在这种应用下,通常不可能会获取一张达标中10%的数据,大部分都是通过索引返回几条记录即可。根据B+树索引的原理可知,对于一张大表,一般的B+树需要2~3次磁盘IO。因此B+树可以很好地完成操作,不需要分区的帮助。并且设计不好的分区会带来严重的性能问题,
比如1000行的表,对主键做10个hash分区,这样每个分区就只有100w的数据了,因此查询应该变得快了,但是有没有考虑这样一种情况:100w和1000w行的数据本身构成B+树层次都是一样的,可能是2层。那么走主键分区的索引并不会带来性能的提高。如果1000wB+树的高度是3层,100w的是2层,那么按照主键索引可以避免1次IO,从而提高了效率。这是对主键索引进行查询,但是如果对其他列进行查询,这时需要扫描10个分区,每个分区的开销是2次IO,一共20次IO。而对原来的单表设计,对于列的查询只有2~3次IO。
因此,对于使用innodb存储引擎作为OLTP应用的表在试用分区时应该十分小心,设计时确认数据的访问模式,否则在OLTP应用下分区可能不仅不会带来查询速度的提高,反而可能会是你的应用执行的更慢。

分区类型

range,list,hash,key这四种分区中,分区的条件是:数据必须是整型,如果不是整型,那应该通过函数将其转化为整型(如:YEAR(),TO_DAYS(),MONTH()等函数)。

range分区


create table sales (
money int unsigned not null,
date datetime
) engine=innodb
partition by range (TO_DAYS(date)) (
partition p201001 values less than (TO_DAYS('2010-02-01')),
partition p201002 values less than (TO_DAYS('2010-03-01')),
partition p201003 values less than (TO_DAYS('2010-04-01'))
);

对于range分区的查询,优化器只能对YEAR(),TO_DAYS(),TO_SECONDS(),UNIX_TIMESTAMP()这类函数进行优化分区。

list分区


create table t1(
a int,
b int
) engine=innodb
partition by list(b) (
partition p0 values in (1,3,5,7,9),
partition p1 values in (0,2,4,6,8)
);

list分区,如果是插入多行数据时,有不符合分区规则情况下,myisam存储引擎会存放符合分区规则的,而innodb会把它看成一个事务,不会插入数据,会报错

hash分区


--- hash分区 是将数据均匀的分配到预先定义的各个分区中,保证各分区的数量大致都是一样的
--- 要使hash分区来分割一个表,要在create table 语句上添加“partition by hash(expr)”子句,其中expr是一个返回一个整数的表达式,它可以仅仅是字段类型为mysql整型的列名。
--- 此外用户很可能需要在后面再添加一个"partitions num"子句,其中num是一个非负整数,表示表将要分割成分区的数量,没有这个子句,默认是1
create table t2(
a int,
b datetime
) engine=innodb
partition by hash (year(b))
partitions 4;

hash分区是取模算法:如b为2010-04-01时 mod(year('2010-04-01'), 4) = mod(2010, 4) = 2 因此记录会被放入分区p2中。

另一种hash分区——linear hash(hash算法不同)


这种分区算法的优点是:增加、删除、合并、和拆分分区将变得更加快捷,有利于含有处理大量数据的表。
缺点是:与使用hash分区得到的数据分布相比,各个分区间数据的分布可能不大均匀。

create table t3(
a int,
b datetime
)engine=innodb
partition by linear hash (year(b))
partitions 4;

分区算法是:同样是2010-04-01
1、取大于分区数量num=4的下一个2的幂值V,V = power(2, ceiling(log(2, NUM))) = 4;即log以2为底num的指数作为2的幂值。2^log(2, num)
2、所在分区N = YEAR('2010-04-01') & (V - 1) = 2

key分区


key分区和hash分区相似,不同之处在于hash分区使用用户定义的函数进行分区,key分区使用MySQL数据库提供的函数进行分区。对于NDB cluster引擎,MySQL数据库使用MD5函数分区,对于其他的数据库引擎,MySQL数据库使用其内部的哈希函数,这些函数基于与password()一样的运算法则

create table t4(
a int,
b datetime
)engine=innodb
partition by key (b)
partitions 4;

在key分区中使用关键字linear和在hash分区中使用具有相同的效果,分区标号是通过2的幂算法(powers-of-two)得到的,而不是通过模数算法。

columns分区


MySQL5.5版本开始支持columns分区,可以看做range分区和list分区的一种进化。
columns分区可以直接使用非整型的数据进行分区,分区根据类型直接比较而得,不需要转化为整型。
columns分区支持以下的数据类型:
1、所有的整数类型,如int,smallint,tinyint,mediumint,bigint。float和decimal则不予支持
2、日期类型,如date和datetime。其余的日期类型不予支持。
3、字符串类型,如char,varchar,binary和varbinary。blob和text类型不予支持。
range columns

create table t5(
a int,
b datetime
)engine=innodb
partition by range columns (b) (
partition p0 values less than ('2009-01-01'),
partition p1 values less than ('2010-01-01')
);

range columns 分区可以对多个列的值进行分区。

create table t5_rcx(
a int,
b int,
c char(3),
d int
)engine=innodb
partition by range columns (a,d,c) (
partition p0 values less than (5, 10, 'ggg'),
partition p1 values less than (10, 20, 'mmm'),
partition p2 values less than (15, 20, 'sss'),
partition p3 values less than (maxvalue, maxvalue, maxvalue)
);

list columns

中文也可以
create table t6(
first_name varchar(25),
last_name varchar(25),
street_1 varchar(30),
street_2 varchar(30),
city varchar(15),
renewal date
)engine=innodb
partition by list columns (city) (
partition pRegion_1 values in ('北京','上海','广州'),
partition pRegion_2 values in ('武汉','郑州','成都')
);

子分区


子分区是指在分区的基础上再进行分区,也称该分区为复合分区。MySQL允许在range和list的分区上再进行hash和key的子分区。

create table ts(
a int,
b date
)engine=innodb
partition by range (YEAR(b))
subpartition by hash(TO_DAYS(b))
subpartitions 2
(
partition p0 values less than (1990),
partition p1 values less than (2000),
partition p2 values less than maxvalue
);
b列进行range分区,又进行了一次hash分区,分区的数量是(3 x 2 = 6)

我们也可以使用subpartition语法显示的指出各个子分区的名字:

create table dspy_sub_name(
a int,
b date
)engine=innodb
partition by range (YEAR(b))
subpartition by hash (TO_DAYS(b))
(
partition p0 values less than (2009) (
subpartition s0,
subpartition s1
),
partition p1 values less than (2010) (
subpartition s2,
subpartition s3
),
partition p2 values less than maxvalue (
subpartition s4,
subpartition s5
)
);

子分区建立需要注意以下几个问题:
1、每个子分区的数量必须相同
2、要在一个分区表的任何分区上使用subpartition明确定义任何子分区,就必须定义所有的子分区。
3、每个subpartition子句必须包括子分区的一个名字
4、子分区的名字必须是唯一的。

子分区可以用于特别大的表,在多个磁盘间分别分配数据和索引。假设有6个磁盘,分别为/disk0,/disk1,/disk2等,现在考虑下面的例子:

create table ts1(
a int,
b date
)engine=innodb
partition by range (YEAR(b))
subpartition by hash (TO_DAYS(b))
(
partition p0 values less than (2009) (
subpartition s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
subpartition s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
partition p1 values less than (2010) (
subpartition s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
subpartition s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
partition p2 values less than (2011) (
subpartition s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
subpartition s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);

由于innodb存储引擎使用表空间自动的进行数据和索引的管理,因此会忽略DATA DIRECTORY 和INDEX DIRECTORY语法,因此上述分区表的数据和索引文件的分开放置对其是无效的。

分区中的null值


mysql数据库允许对null值做分区。MySQL数据库的分区总是把null值看做是小于任何一个非null值,这和MySQL数据库中处理null值得order by操作是一样的。因此对于不同的分区类型,MySQL数据库对于null值的处理也是不相同的。
1、对于range分区,如果向分区中插入null值,则MySQL数据库会将该值放入最左边的分区,另外注意的是如果删除最左边的分区,则会删除该分区的记录包括null值的记录
2、list分区下要使用null值,则必须显示地指出哪个分区中放入null值,否则会报错。

create table t(
int a,
int b
)engine=innodb
partition by list (b) (
partition p0 values in (1,3,5,7,9,null),
partition p1 values in (0,2,4,6,8)
);

3、hash和key分区对于null的处理方式和range分区、list分区不一样。任何分区的函数都会讲含有null值得记录返回为0

在表和分区间交换数据


MySQL5.6开始支持alter table table_name exchange partition partition_name with table table_name的语法。该语法允许分区或子分区中的数据与另一个非分区的表中的数据进行交换。如果纷纷去表中的数据为空,那么相当于将分区中的数据移动到非分区表中。若分区表中的数据为空,则相当于将外部表中的数据导入到分区中。
要使用这个语法要满足以下条件:
1、要交换的表必须和分区表有相同的表结构,但是要交换的表不能含有分区
2、在非分区表中的数据必须在交换的分区定义内
3、被交换的表中不能含有外键或者其他的表含有对该表的外键引用
4、用户除了需要alter,insert,create权限外,还需要有drop权限
另外,有两个小细节需要注意:
1、使用该语句时不会触发交换表和被交换表上的触发器
2、auto_increment列将被重置

create table e(
id int not null,
fname varchar(30),
lname varchar(30)
)engine=innodb
partition by range (id) (
partition p0 values less than (50),
partition p1 values less than (100),
partition p2 values less than (150),
partition p3 values less than maxvalue
);
--- 插入数据
insert into e values
(1669, 'Jim', 'Smith'),
(337, 'Mary', 'Jones'),
(16, 'Frank', 'White'),
(2005, 'Jerry', 'Tom');
--- 创建e2表,复制e表结构,并清除partition
create table e2 like e;
alter table e2 remove partitioning;
--- 交换数据
alter table e exchange partition p0 with table e2;

结果:

mysql分区(partition)相关推荐

  1. MySQL分区Partition

    概述 随着MySQL单表的数据量越来越大,即使有加索引,查询速度也会越来越慢.如果历史数据无用,可以使用硬删除,但即使把这些数据删除,但底层的数据文件并没有变小.面对这类问题,最有效的方法就是在使用分 ...

  2. mysql truncate partition_实战mysql分区(PARTITION)

    前些天拿到一个表,将近有4000w数据,没有任何索引,主键.(建这表的绝对是个人才) 这是一个日志表,记录了游戏中物品的产出与消耗,原先有一个后台对这个表进行统计.....(这要用超级计算机才能统计得 ...

  3. add partition mysql_实战mysql分区(PARTITION)

    前些天拿到一个表,将近有4000w数据,没有任何索引,主键.(建这表的绝对是个人才) 这是一个日志表,记录了游戏中物品的产出与消耗,原先有一个后台对这个表进行统计.....(这要用超级计算机才能统计得 ...

  4. 理解MySQL——并行数据库与分区(Partition)

    1.并行数据库 1.1.并行数据库的体系结构 并行机的出现,催生了并行数据库的出现,不对,应该是关系运算本来就是高度可并行的.对数据库系统性能的度量主要有两种方式:(1)吞吐量(Throughput) ...

  5. MySQL数据库:分区Partition

    一.分区: 分区就是将表的数据按照特定规则存放在不同的区域,也就是将表的数据文件分割成多个小块,在查询数据的时候,只要知道数据数据存储在哪些区域,然后直接在对应的区域进行查询,不需要对表数据进行全部的 ...

  6. mysql的partition分区

    前言:当一个表里面存储的数据特别多的时候,比如单个.myd数据都已经达到10G了的话,必然导致读取的效率很低,这个时候我们可以采用把数据分到几张表里面来解决问题. 方式一:通过业务逻辑根据数据的大小通 ...

  7. mysql分区为什么提高性能_通过分区(Partition)提升MySQL性能

    通过分区(Partition)提升MySQL性能 --MySQL5.1新特性翻译系列 几年前,俺写过一篇题为"The Foundation of Excellent Performance& ...

  8. mysql按照省市给表分区_表分区-partition

    partition分区: 设置分区限制,t0:1-10,t1:10-20,t2:20-最大值: 插入数据后可以看到topic表出现了t0.t1.t2: 按照散点值分区: 创建地区表: 建立会员表,根据 ...

  9. 第18章:MYSQL分区

    第18章:分区 目录 18.1. MySQL中的分区概述18.2. 分区类型 18.2.1. RANGE分区18.2.2. LIST分区18.2.3. HASH分区18.2.4. KEY分区18.2. ...

最新文章

  1. IE6下fixed失效的解决方法
  2. Tomcat【环境搭建 02】Web端403 Access Denied You are not authorized to view this page解决方法(Tomcat 10.2.12 版本)
  3. Qt -- 非常详细的pro文件的语法说明
  4. tensorflow综合示例4:逻辑回归:使用Estimator
  5. ExtJs 4.x Ajax简单封装
  6. 一次较为完整的原生JavaScript AJAX与Java的前后端数据交互
  7. Windows Phone 用WebBrowser加载HTML页面
  8. linux上开发应用程序_如何在Linux上安装软件应用程序
  9. java https post get请求_JAVA利用HttpClient进行POST和GET请求(HTTPS)
  10. [转载] [Python图像处理] 二十二.Python图像傅里叶变换原理及实现
  11. wap绿色传奇搭建(纯净版)
  12. 山大继续教育计算机答案蒙版,2020年计算机一级Photoshop考试基础自测题与答案...
  13. 利用php的GD库封装的海报demo
  14. 【温故而知新-Javascript】使用 Ajax
  15. 华为海思总裁:压在保密柜里面的芯片可以拿出来了
  16. 在线职教行业或将迎来下一个千亿市场
  17. 百度云盘搜索引擎微信公证号_全L导演 H265 1080P 双语版@微信公众号edy521
  18. SQL——子查询的概念及使用
  19. VMware下Linux与Windows共享文件
  20. flutter截取字符串_Flutter Dart List.map() 获取下标

热门文章

  1. 一位算法工程师对自己工作的反思,写的不错。
  2. 来听听一位『大龄程序员』的心声
  3. 豆瓣电台歌曲链接信息
  4. 病毒木马查杀实战第010篇:QQ盗号木马之十六进制代码分析
  5. 大数据风控---Credit Kama商业模式分析
  6. oracle中yest,在Oracle中声明YESTERDAYS日期作为变量
  7. 成都java培训一般需要多久
  8. 自定义注解和AOP的结合
  9. 数学之路(3)-数据分析(5)
  10. C++ Traits编程技法--从迭代器的设计看参数推导与类型推导