zoukankan      html  css  js  c++  java
  • MySQL分区类型

    一、RANGE分区

    RANGE分区是基于属于一个给定连续区间的列值,把多行分配给分区。这些区间要连续且不能相互重叠,使用values less than操作符来进行定义。

    mysql> create table test01 (
    id int not null,
    fname varchar(30),
    lname varchar(30),
    hired date not null default '1970-01-01',
    separated date not null default '9999-12-31',
    job_code int not null,
    store_id int not null )
    partition by range (store_id) (
    partition p0 values less than (6),
    partition p1 values less than (11),
    partition p2 values less than (16),
    partition p3 values less than (21) );
    #创建一个RANGE分区方式的表
    

    按照这种分区方案,当插入的记录store_id小于6,会保存在p0这个分区,如果store_id小于11则会将数据保存在p1这个分区.....以此类推。但是在上面的分区方案中,定义的最后一个分区是小于21的,那么,如果此时有store_id大于或等于21的记录,则会插入失败,因为数据库不知道应该插入到哪个分区中,避免这种情况的发生,就需要在指定分区方案或者新增一个分区,最后一个分区指定的范围应该为maxvalue,而不是一个具体的值。

    根据上面创建的表,可以添加一个范围为maxvalue的分区,命令如下:

    mysql> alter table test01 add partition(partition p4 values less than maxvalue);
    

    如果最后一个分区指定的范围是maxvalue,那么后期想要添加分区的话,需要使用以下方式(使用类似于分区合并的指令):

    mysql> alter table test01 reorganize partition p4 into
    (partition p03 values less than (25),
    partition p04 values less than maxvalue );
    

    删除分区的指令如下(注:当分区被删除,那么分区所存储的数据也将被删除,慎用!!!)

    mysql> alter table test01 drop partition p2;
    

    二、LIST分区

    LIST分区类似于RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。LIST分区通过使用partition by list (expr)来实现,其中“expr”是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过values in (value_list)的方式来定义每个分区,其中“value_list”是一个通过逗号分隔的整数列表。

    mysql> create table test02 (
    id int not null,
    fname varchar(30),
    lname varchar(30),
    hired date not null default '1970-01-01',
    separated date not null default '2100-12-31',
    job_code int,
    store_id int )
    partition by list(store_id)(
    partition pNorth values in (3,5,6,9,17),
    partition pEast values in (1,2,10,11,19,20),
    partition pWest values in (4,12,13,14,18),
    partition pCentral values in (7,8,15,16) );
    #创建LIST分区类型的表
    

    在上面创建的表中,如果插入一个store_id为22(不在定义的分列表中)的数据,那么将会插入失败,如下:

    mysql> insert into test02(id,fname,lname,job_code,store_id)
    values (12,'tom','TOM',42,22);
    ERROR 1526 (HY000): Table has no partition for value 22
    

    失败的原因就是:LIST分区没有类似如“VALUES LESS THAN MAXVALUE”这样的包含其他值在内的定义。将要匹配的任何值都必须在值列表中找到!

    解决方法就是增加有这个值的分区,如下:

    mysql> alter table test02 add partition (partition p4 values in (22));
    

    三、HASH分区

    这种模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。 hash分区的目的是将数据均匀的分布到预先定义的各个分区中,保证各分区的数据量大致一致。在range和list分区中,必须明确指定一个给定的列值或列值集合应该保存在哪个分区中;而在hash分区中,MySQL自动完成这些工作,用户所要定一个列值或者表达式,以及指定被分区的表将要被分割成的分区数量。

    mysql> create table test03(a int(11),b datetime) partition by hash(year(b)) partitions 4;
    #创建hash分区类型的表
    mysql> insert into test03 values(1,'2010-1-1');
    #插入数据
    mysql> select mod(year('2010-1-1'),4);
    +-------------------------+
    | mod(year('2010-1-1'),4) |
    +-------------------------+
    |                       2 |
    +-------------------------+
    #查询数据存放在哪个分区,显示在第2个分区
    mysql> select * from information_schema.partitions 
    where table_schema='test02' and table_name='test03'G
    # 查看information_schema库中的partitions也可以查看到p2分区中会有1条记录
    *************************** 3. row ***************************
                    TABLE_CATALOG: def
                     TABLE_SCHEMA: test02
                       TABLE_NAME: test03
                   PARTITION_NAME: p2     #当前分区名称
                SUBPARTITION_NAME: NULL
       PARTITION_ORDINAL_POSITION: 3
    SUBPARTITION_ORDINAL_POSITION: NULL
                 PARTITION_METHOD: HASH
              SUBPARTITION_METHOD: NULL
             PARTITION_EXPRESSION: year(b)
          SUBPARTITION_EXPRESSION: NULL
            PARTITION_DESCRIPTION: NULL
                       TABLE_ROWS: 1      #表示有1条数据
    

    上面的例子并不能把数据均匀的分布到各个分区,因为按照YEAR函数进行的,该值本身是离散的。如果对连续的值进行HASH分区,如自增长的主键,则可以较好地将数据平均分布。

    四、KEY分区

    key分区和hash分区相似,不同在于hash分区是用户自定义函数进行分区,key分区使用mysql数据库提供的函数进行分区,NDB cluster使用MD5函数来分区,对于其他存储引擎mysql使用内部的hash函数。

    mysql> create table test04(a int(11), b datetime) partition by key(b) partitions 4;
    #创建一个key分区类型的表
    #后期如果需要增加分区,可使用以下指令
    mysql> alter table test04 add partition partitions 5;
    #新增5个分区,也就是现在test04表中有9个分区了
    

    注意: mysql-5.5开始支持COLUMNS分区,可视为RANGE和LIST分区的进化,COLUMNS分区可以直接使用非整形数据进行分区。COLUMNS分区支持以下数据类型: 所有整形,如INT SMALLINT TINYINT BIGINT。FLOAT和DECIMAL则不支持。 日期类型,如DATE和DATETIME。其余日期类型不支持。字符串类型,如CHAR、VARCHAR、BINARY和VARBINARY。BLOB和TEXT类型不支持。 COLUMNS可以使用多个列进行分区。

    五、MySQL分表和分区的区别

    5.1 实现方式

    • 分表:是真正的分表,一张表分成很多表后,每一个小表都是完整的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件;
    • 分区:一张大表进行分区后,它还是一张表,不会变成二张表,但是它存放数据的区块变多了;

    5.2 数据处理方面

    • 分表:数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面;
    • 分区:不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表呢,还是一张表,数据处理还是由自己来完成。

    5.3 提高性能方面

    • 分表后,单表的并发能力提高了,磁盘I/O性能也提高了。因为查寻一次所花的时间变短了,如果出现高并发的话,总表可以根据不同的查询,将并发压力分到不同的小表里面;
    • mysql提出了分区的概念,主要是想突破磁盘I/O瓶颈,想提高磁盘的读写能力,来增加mysql性能;
    • 在这一点上,分区和分表的侧重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的;

    5.4 实现的难度方面

    • 分表的方法有很多,用merge来分表,是最简单的一种方式。这种方式跟分区难易度差不多,并且对程序代码来说可以做到透明的;如果是用其他分表方式就比分区麻烦了;
    • 分区实现是比较简单的,建立分区表,和建平常的表没什么区别,并且对开代码端来说是透明的;

    5.5 其他方面

    • 都能提高mysql的性能,在高并发状态下都有一个良好的表现;
    • 分表和分区不矛盾,可以相互配合的,对于那些大访问量,并且表数据比较多的表,我们可以采取分表和分区结合的方式,访问量不大,但是表数据很多的表,我们可以采取分区的方式等;
    • 分表技术是比较麻烦的,需要手动去创建子表,app服务端读写时候需要计算子表名。采用merge好一些,但也要创建子表和配置子表间的union关系;
    • 表分区相对于分表,操作方便,不需要创建子表;

    6六、实现将分区存放在不同的目录

    [root@db01 ~]# mkdir /data
    [root@db01 ~]# chown -R mysql.mysql /data
    #在本地创建所需目录
    mysql> create table user(
    id int not null auto_increment,
    name varchar(30) not null default '',
    primary key(id)) default charset=utf8 auto_increment=1
    partition by range(id)(
    partition p1 values less than (3) data directory '/data/area1',
    partition p2 values less than (6) data directory '/data/area2',
    partition p3 values less than (9) data directory '/data/area3');
    #创建表,对表分区时指定相应的目录
    [root@db01 ~]# tree /data/
    /data/
    ├── area1
    │   └── test02
    │       └── user#P#p1.ibd
    ├── area2
    │   └── test02
    │       └── user#P#p2.ibd
    └── area3
        └── test02
            └── user#P#p3.ibd
    #查看本地目录,则会发现自动创建了相应的存放数据的目录
    

    注意:使用mysql默认的存储引擎inodb创建表时,只需要指定data directory 就可以,因为inodb的数据和索引在一个文件中。但是创建表时指定engine=myisam时,修改分区的存储位置,需要同时指定data directory和index directory。

    *************** 当你发现自己的才华撑不起野心时,就请安静下来学习吧!***************
  • 相关阅读:
    Nginx 的 Location 配置指令块
    linux java环境配置
    WebUploader API文档
    cron表达式详解
    Android中设置自己软件的铃声+震动
    java格式化输出 printf 例子
    Android_Intent意图详解
    MyEclipse Could not create the view: An unexpected exception was thrown解决方案
    HttpClient技术
    java-Object类中的方法
  • 原文地址:https://www.cnblogs.com/lvzhenjiang/p/14197280.html
Copyright © 2011-2022 走看看