HASH分区

HASH分区主要用来分散热点读,确保数据在预先确定个数的分区中尽可能平均分布。对一个表执行HASH分区时,MySQL会对分区键应用一个散列函数,以此确定数据应当放在N个分区中的哪个分区
MySQL支持两种HASH分区,常规HASH分区和线性HASH分区(LINEAR HASH);常规HASH使用的是取模算法,线性HASH分区使用的是一个线性的2的幂的运算法则

使用PARTITION BY HASH(expr)创建hash分区表,expr需要返回一个整数

下面的例子中创建了一个以store_id为分区键的hash分区表,如果你没有写partitions子句,那么默认为partitions 1

CREATE TABLE employees (
    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,
    store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;

你也可以使用一个返回整型的表达是作为分区键

CREATE TABLE employees (
    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,
    store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;

表达式expr必须返回一个非恒定的,非随机整数值(换句话说,应该是变化,但又是确定的)
同时应当注意的是,该表达式在每次insert update时都会被执行从而决定将数据放入哪个分区,所以如该表达式的性能低下,会影响整个分区表的性能
MySQL也不推荐使用涉及多列的hash表达式

常规HASH分区方式看上去挺不错的,通过取模的方式将数据尽可能的平均分布在每个分区中,让每个分区管理的数据都减少了,提高了查询的效率;课时当我们需要增加分区或者合并分区的时候,问题就出现了。假设原来是5个常规HASH分区,现在需要新增一个常规HASH分区,原来的取模算法是MOD(expr,5),根据余数0-4分布在五个分区中,现在新增一个分区,取模算法编程MOD(expr,6),根据余数0-5分布在6个分区中,原来5个分区中的数据大部分需要通过重新计算重新分区。
常规HASH分区在分区管理上带来的代价太大了,不适合需要灵活变动的需求。为了降低分区管理上的代价,MySQL提供了线性HASH分区,分区函数是一个线性的2的幂的运算法则

create table normal_hash(
    id int
)
partition by hash(id)
partitions 5; 

delimiter $$
create procedure normal_insert()
begin
	declare line int default 0;
	while line<1000
	do
		insert into normal_hash values(line);
		set line=line+1;
	end while;
end$$

call normal_insert();

mysql> select
    ->   partition_name part,
    ->   partition_expression expr,
    ->   partition_description descr,
    ->   table_rows
    -> from information_schema.partitions  where
    ->   table_schema = schema()
    ->   and table_name='normal_hash';
+------+------+-------+------------+
| part | expr | descr | table_rows |
+------+------+-------+------------+
| p0   | id   | NULL  |        200 |
| p1   | id   | NULL  |        200 |
| p2   | id   | NULL  |        200 |
| p3   | id   | NULL  |        200 |
| p4   | id   | NULL  |        200 |
+------+------+-------+------------+

线性hash分区

线性HASH分区和常规HASH分区在语法上的唯一区别是在”PARTITION BY”子句中添加LINEAR关键字

CREATE TABLE employees (
    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,
    store_id INT
)
PARTITION BY LINEAR HASH( YEAR(hired) )
PARTITIONS 4;

使用线性HASH是,指定记录保存在哪个分区是可以计算出来的,假设将要保存的记录的分区编号设为N,num是一个非负整数,表示分割成分区的数量,那么N可以通过以下算法得到

首先,找到一个大于等于num的2的幂,这个值设为V,V可以通过下面的公式得到
V = POWER(2, CEILING(LOG(2, num)))
例如,刚才创建的employees表预先设定了4个分区,num=4
V = POWER(2, CEILING(LOG(2, 4)))
= POWER(2, CEILING(2))
= POWER(2, 2)
= 4

其次,设置N = F(column_list) & (v-1)
例如,我们刚才计算出V=4,现在计算stroe_id=234对于的值
N = F(column_list) & (v-1)
= 234 & (4-1)
= 2

当 N>=num
设置V=Ceiling(v/2),这时N=N & (V-1)
对于store_id=234这条记录,由于N=2<4;所以直接就能够判断这条记录会被存储在第二个分区中

V = POWER(2, CEILING( LOG(2,6) )) = 8
N = YEAR('2003-04-14') & (8 - 1)
   = 2003 & 7
   = 3

(3 >= 6 is FALSE: record stored in partition #3)

V = 8
N = YEAR('1998-10-19') & (8-1)
  = 1998 & 7
  = 6

(6 >= 6 is TRUE: additional step required)

N = 6 & CEILING(8 / 2)
  = 6 & 3
  = 2

(2 >= 6 is FALSE: record stored in partition #2)

有意思的是,当线性HASH分区的个数是2的N次冥时,线性HASH分区的结果和常规HASH分区的结果是一致的

线性HASH分去的有点事,在分区维护(包括增加、删除、合并、拆分分区)时,MySQL能够处理的更加迅速;缺点是,对比常规HASH分区(取模)的时候,线性HASH各个分区之间数据的分布不太均衡

Mysql --分区表(6)Hash分区的更多相关文章

  1. Mysql --分区表(7)Key分区

    Key分区 按照Key进行分区非常类似于按照Hash进行分区,只不过Hash分区允许使用用户自定义的表达式,而Key分区不允许使用用户自定义的表达式,需要使用MySQL服务器提供的HASH函数;同时H ...

  2. mysql分区表之一:分区原理和优缺点【转】

    1.分区表的原理 分区表是由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们也可以直接访问各个分区,存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分 ...

  3. MySQL 分区表,为什么分区键必须是主键的一部分?

    随着业务的不断发展,数据库中的数据会越来越多,相应地,单表的数据量也会越到越大,大到一个临界值,单表的查询性能就会下降. 这个临界值,并不能一概而论,它与硬件能力.具体业务有关. 虽然在很多 MySQ ...

  4. Mysql --分区表(5)Columns分区

    COLUMNS分区 COLUMNS分区是RANGE和LIST分区的变种.COLUMNS分区支持多列作为分区键进行分区 RANGE COLUNMS分区和LIST COLUMNS都支持非INT型列作为分区 ...

  5. MySQL分区表例子——List分区

    列表分区(List分区) 这里假设表中有一个sale_item_type 字段,数据类型为INT 型 当sale_item_type 为1,3,5的时候,作为一个分区 当sale_item_type  ...

  6. mysql分区表之二:MySQL的表的四种分区类型介绍

    一.什么是表分区 通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了.如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区 ...

  7. 高性能可扩展mysql 笔记(三)Hash分区、RANGE分区、LIST分区

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.MySQL分区表操作 1.定义:数据库表分区是数据库基本设计规范之一,分区表在物理上表现为多个文件, ...

  8. MySQL HASH分区

    200 ? "200px" : this.width)!important;} --> 介绍 基于给定的分区个数,将数据分配到不同的分区,HASH分区只能针对整数进行HASH ...

  9. [MySQL Reference Manual] 20 分区

    20 分区 20 分区 20.1 MySQL的分区概述 20.2 分区类型 20.2.1 RANGE分区 20.2.2 LIST分区 20.2.3 COLUMNS分区 20.2.3.1 RANGE C ...

随机推荐

  1. 关于UIView的autoresizingMask属性的研究【转】

    在 UIView 中有一个autoresizingMask的属性,它对应的是一个枚举的值(如下),属性的意思就是自动调整子控件与父控件中间的位置,宽高. 1 2 3 4 5 6 7 8 9 enum  ...

  2. nginx for linux安装及安装错误解决

    nginx:下载地址:http://www.nginx.org/ 1.GCC编译器 安装指令 :yum  install -y  gcc 如果你所使用的是ubuntu,则安装指令为:apt-get i ...

  3. PHP常见方法

    1.获取字符串长度: preg_match_all('/./us', $only, $match); echo count($match[0]); 2.Php除法取整 2.1.round — 对浮点数 ...

  4. 做一个高效的IOS开发工程师

    最近觉得自己的开发效率太慢了,总结了一下:熟练度不够是一方面,经常用到东西查看一下,积累问题?一方面,这个无法分享的.现在主要分享的是:如何高效的用好自己的时间. 1.善用xcode. xcode实在 ...

  5. NK3C 业务权限控制

    资源中,添加了一个类型:权限(橙色显示),现在有4种数据: 域管理员:domainAdmin 组织管理员:orgAdmin 组管理员:groupAdmin 一线员工:phoneAdmin 权限控制可以 ...

  6. linux shell学习笔记

    一  变量 声明变量: my_var='ddd'使用变量: ${my_var}设置为只读变量: readonly my_var删除变量: unset my_var 注意只读变量不能被删除 变量类型:( ...

  7. C# 连接 Oracle 的几种方式

    一:通过System.Data.OracleClient(需要安装Oracle客户端并配置tnsnames.ora)1. 添加命名空间System.Data.OracleClient引用2. usin ...

  8. 为什么匿名内部类和局部内部类只能访问final变量

    因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或 ...

  9. VC++ chap13 文档与串行化

    Lesson 13 文档与串行化 13.1使用CArchive类对文件进行读写操作 //让对象数据持久性的过程称之为串行化,或者序列化 void CGraphicView::OnFileWrite() ...

  10. wget net-tools

    新安装的centos7 minimal 没有安装 wget 需要安装一下,才能安装lnmp yum -y install wget yum -y install net-tools