MySQL分区之HASH分区详解

 更新时间:2022年04月13日 10:50:07   作者:pursuer.chen  
hash分区的目的是将数据按照某列进行hash计算后更加均匀的分散到各个分区,下面这篇文章主要给大家介绍了关于MySQL分区之HASH分区的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

介绍

基于给定的分区个数,将数据分配到不同的分区,HASH分区只能针对整数进行HASH,对于非整形的字段只能通过表达式将其转换成整数。表达式可以是mysql中任意有效的函数或者表达式,对于非整形的HASH往表插入数据的过程中会多一步表达式的计算操作,所以不建议使用复杂的表达式这样会影响性能。

MYSQL支持两种HASH分区,常规HASH(HASH)和线性HASH(LINEAR HASH)。

一、常规HASH

常规hash是基于分区个数的取模(%)运算。根据余数插入到指定的分区

CREATE TABLE tbhash (
    id INT NOT NULL,
    store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4
;
ALTER TABLE tbhash ADD INDEX ix_store_id(store_id);
INSERT INTO tbhash() VALUES(1,100),(1,101),(2,102),(3,103),(4,104);

SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION 
FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tbhash';

其中100,104对4取模是0所以这两条数据被分配到了p0分区。

2.时间类型字段

CREATE TABLE employees (
    id INT NOT NULL,
    hired DATE NOT NULL DEFAULT '1970-01-01',
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;

常规hash的分区非常的简便,通过取模的方式可以让数据非常平均的分布每一个分区,但是由于分区在创建表的时候已经固定了。如果新增或者收缩分区的数据迁移比较大。

二、线性HASH(LINEAR HASH)

LINEAR HASH和HASH的唯一区别就是PARTITION BY LINEAR HASH

CREATE TABLE tblinhash (
    id INT NOT NULL,
    hired DATE NOT NULL DEFAULT '1970-01-01'
)
PARTITION BY LINEAR HASH( YEAR(hired) )
PARTITIONS 6;

线性HASH的计算原理如下:

假设分区个数num=6,N表示数据最终存储的分区

sep1:V = POWER(2, CEILING(LOG(2, num))),LOG()是计算NUM以2为底的对数,CEILING()是向上取整,POWER()是取2的次方值;如果num的值是2的倍数那么这个表达式计算出来的结果不变。

V=POWER(2,CEILING(LOG(2,6)))

V=POWER(2,3)

V=8

sep2:N=values&(V-1);&位与运算,将两个值都转换成2进行求与运算,当都为1才为1;当num是2的倍数时由于V计算出来的结果不变,这时values&(V-1)=MOD(values/num)和时间HASH取模算出的结果是一致的,这时特殊情况只有当分区是2的倍数才是这种 情况。values是YEAR(hired)的值

sep3:while N>=num

sep3-1:N=N& (CEIL(V/ 2)- 1)

例如:

1.当插入的值是'2003-04-14'时

    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),N不大于num所以存储在第3分区,注意这里的3指的是P3,分区号是从P0开始。

2.当插入的值是‘1998-10-19’

V = POWER(2, CEILING( LOG(2,6) )) = 8

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

= 1998 & 7

= 6

(6 >= 6 is TRUE: additional step required),由于N>=num所以要进行第三步操作

N=N&(CEILING(8/2)-1)

=6&3

=2

(2>=6is FALSE:recored in partition #2),由于2不大于6所以存储在第2个分区,注意这里的3指的是P2,分区号是从P0开始。

INSERT INTO tblinhash() VALUES(1,'2003-04-14'),(2,'1998-10-19');
SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION 
FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tblinhash';

EXPLAIN SELECT * FROM tblinhash WHERE hired='2003-04-14';

三、分区管理

常规HASH和线性HASH的增加收缩分区的原理是一样的。增加和收缩分区后原来的数据会根据现有的分区数量重新分布。HASH分区不能删除分区,所以不能使用DROP PARTITION操作进行分区删除操作;

只能通过ALTER TABLE ... COALESCE PARTITION num来合并分区,这里的num是减去的分区数量;

可以通过ALTER TABLE ... ADD PARTITION PARTITIONS num来增加分区,这里是null是在原先基础上再增加的分区数量。

1.合并分区

减去3个分区

ALTER TABLE tblinhash COALESCE PARTITION 3;
SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION 
FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tblinhash';

注意:减去两个分区后,数据根据现有的分区进行了重新的分布,以'2003-04-14'为例:POWER(2, CEILING( LOG(2,3) ))=4,2003&(4-1)=3,3>=3,3&(CEILING(3/2)-1)=1,所以现在的'2003-04-14'这条记录由原来的p3变成了p1

2.增加分区

增加4个分区

ALTER TABLE tblinhash add PARTITION partitions 4;
SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION 
FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tblinhash';

当在3个分区的基础上增加4个分区后,‘2003-04-14’由原来的p1变成了p3,而另一条记录由原来的p2变成了p6

四、移除表的分区

ALTER TABLE tablename
REMOVE PARTITIONING ;

注意:使用remove移除分区是仅仅移除分区的定义,并不会删除数据和drop PARTITION不一样,后者会连同数据一起删除

分区系列文章:

RANGE分区:https://www.jb51.net/article/244269.htm

COLUMN分区:https://www.jb51.net/article/96515.htm

LIST分区:https://www.jb51.net/article/244256.htm

HASH分区:https://www.jb51.net/article/244277.htm

KEY分区:https://www.jb51.net/article/244282.htm

子分区:https://www.jb51.net/article/244294.htm

指定各分区路径:https://www.jb51.net/article/244296.htm

分区索引以及分区介绍总结:https://www.jb51.net/article/244300.htm

总结

常规HASH的数据分布更加均匀一些,也便于理解;目前还没有彻底理解为什么线性HASH在收缩和增加分区时处理的速度会更快,同时线性HASH的数据分布不均匀。

到此这篇关于MySQL分区之HASH分区的文章就介绍到这了,更多相关MySQL HASH分区内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解MySQL数据类型DECIMAL(N,M)中N和M分别表示的含义

    详解MySQL数据类型DECIMAL(N,M)中N和M分别表示的含义

    关于MySQL数据类型decimal中n和m分别表示什么含义?本文就此问题作了简单论述,并创建相关表进行验证,需要的朋友可以了解下。
    2017-10-10
  • mysql中关键词exists的用法实例详解

    mysql中关键词exists的用法实例详解

    在mysql中exists用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回true或false,下面这篇文章主要给大家介绍了关于mysql中关键词exists用法的相关资料,需要的朋友可以参考下
    2022-06-06
  • Ubuntu安装Mysql+启用远程连接的完整过程

    Ubuntu安装Mysql+启用远程连接的完整过程

    这篇文章主要介绍了Ubuntu如何安装Mysql+启用远程连接,用ssh客户端或者云服务器厂家提供的网页版控制台都行,只要你能连上服务器就行,需要的朋友可以参考下
    2022-06-06
  • Mysql 5.7.20压缩版下载和安装简易教程

    Mysql 5.7.20压缩版下载和安装简易教程

    这篇文章主要介绍了Mysql 5.7.20压缩版下载和安装简易教程,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-11-11
  • 在idea中使用mysql数据库超详细教程

    在idea中使用mysql数据库超详细教程

    这篇文章主要介绍了如何在IntelliJ IDEA中连接MySQL数据库,并使用控制台执行SQL语句,还详细讲解了如何使用MyBatis Generator快速生成实体类、接口和SQL文件,以及如何解决Lombok依赖问题,需要的朋友可以参考下
    2025-02-02
  • 安装SQL server出现“服务没有及时响应启动或控制请求”的解决方案

    安装SQL server出现“服务没有及时响应启动或控制请求”的解决方案

    这篇文章主要给大家解决了安装SQL server出现“服务没有及时响应启动或控制请求”,文中有详细的解决方案,有需要的同学可以参考阅读下
    2023-08-08
  • Mysql如何查询近30天活跃用户数

    Mysql如何查询近30天活跃用户数

    这篇文章主要介绍了Mysql查询近30天活跃用户数,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • MySQL删除表数据与MySQL清空表命令的3种方法浅析

    MySQL删除表数据与MySQL清空表命令的3种方法浅析

    删除现有MySQL表非常容易,但是删除任何现有的表时要非常小心,因为删除表后丢失的数据将无法恢复,下面这篇文章主要给大家介绍了关于MySQL删除表数据与MySQL清空表命令的3种方法的相关资料,需要的朋友可以参考下
    2022-08-08
  • MySql中深度分页的问题处理

    MySql中深度分页的问题处理

    这篇文章主要介绍了MySql中深度分页的问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • mysql字符串拼接的几种实用方式小结

    mysql字符串拼接的几种实用方式小结

    在SQL语句中经常需要进行字符串拼接,下面这篇文章主要给大家介绍了关于mysql字符串拼接的几种实用方式,文中通过图文以及代码示例介绍的非常详细,需要的朋友可以参考下
    2023-11-11

最新评论