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. 剑指offer习题集1

    1.打印二叉树 程序很简单,但是其中犯了一个小错误,死活找不到,写代码要注意啊 这里左右子树,要注意是node->left,结果写成root->left vector<int> ...

  2. 20. Candy && Gas Station

    Candy There are N children standing in a line. Each child is assigned a rating value. You are giving ...

  3. lua 中的面向对象

    lua 是一种脚步语言,语言本身并不具备面向对象的特性. 但是我们依然可以利用语言的特性,模拟出面向对象的特性. 面向对象的特性通常会具备:封装,继承,多态的特性,如何在lua中实现这些特性,最主要的 ...

  4. 删除sde用户问题

    删除SDE用户(GIS地图数据用户),长时间删除没反应,结束drop user sde cascade命令后,重新执行,结果报ORA-00604 ORA-21700 select user_id,us ...

  5. js事件委托,可以使新添加的元素具有事件(event运用)

    miaov视频教程  http://study.163.com/course/courseMain.htm?courseId=231002 <!DOCTYPE html PUBLIC " ...

  6. Inside The C++ Object Model - 03

    object Lessons 1.C++中布局以及存取时间上的的额外负担是由virtual引起的:virtual function.virtual base class.或是由于多继承引起的. 2.C ...

  7. weed-fs 压力测试

    阅读<Weed-FS/杂草文件系统 小文件存储集群 安装 使用 测试>中提到weedfs的负载压力不是很好,在看过代码后进行了相应测试,未发现负载压力有何问题.   weedfs mast ...

  8. information_schema系列三(文件,变量)

    这个系列的文章主要是为了能够让自己了解MySQL5.7的一些系统表,统一做一下备注和使用,也希望分享出来让大家能够有一点点的受益. 1:FILES 这张表提供了有关在MySQL的表空间中的数据存储的文 ...

  9. asp.net截取指定长度的字符串内容

    /// <summary> /// 用于截取指定长度的字符串内容 /// </summary> /// <param name="sString"&g ...

  10. 使用python的subprocess启动windows程序提示WindowsError: [Error 6] The handle is invalid

    代码如下: subp = subprocess.Popen(cwd_path + "test.exe", cwd = cwd_path, shell = True, stdout ...