MySQL优化表分区

 转载于:https://www.bilibili.com/video/BV1E7411q7Nx?p=1

一、RANGE分区

  • 基于属于一个给定连续区间的列值,把多行分配给分区。
  • 这些区间要连续且不能相互重叠,使用VALUES LESS THAN操作符来进行定义。
-- RANGE分区案例
create table t_student
(
    id varchar(50) not null,
    name varchar(20),
    age int,
    primary key (id,age)
)
partition by range(age)
(
    partition p01 VALUES less than (10),
    partition p02 VALUES less than (20),
    partition p03 VALUES less than (30),
    partition p04 VALUES less than (MAXVALUE)
);

二、LIST分区

  • 类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
  • LIST分区通过使用"PARTITION BY LIST(expr)"来实现,其中"expr" 是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过"VALUES IN (value list)"的方式来定义每个分区,其中"value list"是一个通过逗号分隔的整数列表。
-- LIST分区案例
-- LIST分区案例对于一个综合性的网店来说,商品分为诸多种类。我们可以按照商品ID进行range分区,也可以按照商品的类型划分分区。在这个例子中, LIST分区给了我们更多的选择。
create table t_commodity 
(
    id varchar(50) not null,
    cid int,
    name varchar(20),
    date datetime
)
partition by list (cid) 
(
    partition po1 values in (1,2,3),
    partition po2 values in (4,5,6), 
    partition po3 values in (7,8,9) 
);    

三、HASH分区

  • 基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式。
  • 要使用HASH分区来分割一个表,要在CREATE TABLE语句上添加一个"PARTITION BY HASH (expr)"子旬,其中"expr"是一个返回一个整数的表达式。它可以仅仅是字段类型为MySQL整型的一列的名字。此外,你很可能需要在后面再添加一个"PARTITIONS num"子句,其中num是一个非负的整数,它表示表将要被分割成分区的数量。如果没有"PARTITIONS num"子句,那么分区的数量将默认为1。
  • 使用HASH分区的优点在于数据分布较为均匀。
-- HASH分区案例
-- 另外,在MySQL Cluster中,分区行为是自动的。默认情况下,分区的数量和ndb node数量相同。通常在节点数很多的情况下,会通过配置分区数和node group搭配进行调整。
create table t_company1 
(
  id varchar(50) not null,
  cid int,
  name varchar(20),
  date datetime
) 
partition by hash (cid)
partitions 4;

四、LINEAR HASH分区

  • 线性与常规哈希的区别在于,线性哈希功能使用的一个线性的2的幂(powers-of-two )运算法则,而常规哈希使用的是求哈希函数值的模数。
  • 按照线性哈希分区的优点在于增加、删除、合并和拆分分区将变得更加快捷,有利于处理含有极其大量(1T)数据的表。不过, MysQL的线性哈希算法导致相比较常规哈希,数据可能分布的不那么均衡,容易产生"hotspot nodes"。
  • 关于LINEAR HASH算法参见MySQL官方文档:http://dev.mysql.com/doc/refman/5.1/zh/partitioninq.html#partitioning-linear-hash
-- LINEAR HASH分区案例
-- 线性哈希分区和常规哈希分区在语法上的唯一区别在于,在"PARTITION BY" 子句中添加"LINEAR"关键字。
create table t_company2 
(
  id varchar(50) not null,
  cid int,
  name varchar(20),
  date datetime
) 
partition by linear hash (cid)
partitions 4;

五、KEY分区

  • 按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用户定义的表达式,而KEY分区的哈希函数是由MysQL服务器提供。MySQL簇( Cluster )使用函数MD5()来实现KEY分区;对于使用其他存储引擎的表,服务器使用其自己内部的哈希函数,这些函数是基于与PASSWORD()一样的运算法则。
-- KEY分区案例
create table t_company3 
(
  id varchar(50) not null,
  cid int,
  name varchar(20),
  date datetime
) 
partition by linear key (cid)
partitions 4;

六、多列分区

  • COLUMNS关键字允许字符串和日期列作为分区定义列,同时还允许使用多个列定义一个分区。
-- 多列分区案例
create table t_order
(
    a int,
    b int,
    c int
)
partition by range columns(a,b)
(
    partition p01 values less than (10,10),
    partition po2 values less than (10,20),
    partition p03 values less than (10,30), 
    partition p04 values less than (10,maxvalue),
    partition p05 values less than (maxvalue,maxvalue)
);
-- 多列分区案例 -- 多列分区案例第一个分区用来存储雇佣于1990年以前的女职员,第二个分区存储股用于1990-2000年之间的女职员,第三个分区存储所有剩下的女职员。对于分区p04到p06 ,我们策略是一样的,只不过存储的是男职员。最后一个分区是控制情况。 create table t_emplovees ( emp_no int, birth_date datetime, first_name varchar(20), last_name varchar(20), gender char(1), hire_date datetime ) engine=myisam partition by range columns(gender,hire_date) ( partition p01 values less than ('F','1990-01-01'), partition p02 values less than ('F','2000-01-01'), partition p03 values less than ('F',maxvalue), partition p04 values less than ('M', '1990-01-01'), partition p05 values less than ('M','2000-01-01'), partition p06 values less than ('M',maxvalue), partition p07 values less than (maxvalue,maxvalue) );

七、子分区

  • 子分区是分区表中每个分区的再次分割。子分区可以用于特别大的表,在多个磁盘间分配数据和索引。
-- 子分区案例
create table t_order_details 
(
   id int, 
   udate datetime
 )
 partition by range(year(udate))
 subpartition by hash(to_days(udate))
 subpartitions 2
 (
   partition po values less than (1990),
   partition p1 values less than (2000),
   partition p2 values less than maxvalue
 )
-- 子分区案例
-- 将每个子分区保存在不同的存储上,优化1/0性能。
-- 注释:data directory 后跟的是数据存放的文件位置,index directory后跟的是索引存放的文件位置
create table t_order_content
(
    id int,
    udate datetime
)
partition by range(year(udate))
subpartition by hash(to_days(udate))
(
  partition p01 values less than (1990)
   (
     subpartition s0
     data directory ='/var/a/data'
     index directory = '/var/a/idx',
     subpartition s1
     data directory = '/var/b/data'
     index directory = '/var/b/idx'
   ),
   partition p02 values less than (2000)
   (
  subpartition s2
  data directory ='/var/c/data'
  index directory = '/var/c/idx',
  subpartition s3
  data directory = '/var/d/data'
  index directory = '/var/d/idx'
  )
);
上一篇:Kafka高吞吐量的原因


下一篇:一位Java大牛的BAT面试心得与经验总结,附小技巧