目录

  • 1、什么是分区?
  • 2、分类
  • 3、RANGE分区
  • 4、LIST分区
  • 5、HASH分区
  • 6、KEY分区
  • 7、性能比较
  • 8、分区的管理

相关内容:数据库分表分库及分表分库带来的问题

1、什么是分区?

单表数据库本地文件为下表所示:

存储引擎 文件类型 存储内容
MyISAM .frm 存放表结构,字段长度等
.myd 存储数据信息
.myi 存储索引信息
InnoDB .frm 存放表结构,字段长度等
.ibd 存储数据信息和索引信息

如果一张表的数据量很大,那么myd、myi或者ibd就会很大,读写就会很慢。 分区是将数据分段存放在多个位置,可以是不同的硬盘、系统,或者是不同服务器存储介子中。分区后,在逻辑上还是一张表,但底层是由多个物理区块组成。业务读写操作时还是原大表的名字,数据库自动去组织分区的数据。

分区之后,数据文件被分成了很多块,只要知道了所查数据在哪一块,就可以在哪一块上快速查找。

2、分类

RANGE分区:基于一个给定的不重叠的连续区间范围的列值,把多行数据分配到不同的分区。比如:00-09年的数据、10-19年的数据、20年及以后的数据。
LIST分区:类似于range分区,区别在于list分区是基于列值匹配一个离散值集合中的某个值来进行选择。比如:2019年的数据、2020年的数据。
HASH分区:通过对表的一个或多个列的Hash Key进行计算,最后通过得到的Hash码对应到不同的数据分区。
KEY分区:类似于hash分区,但是只能使用MySQL服务器提供的哈希函数进行计算。

说明:(1)在MySQL5.1版本中,RANGE,LIST,HASH分区要求分区键必须是INT类型,或者通过表达式返回INT类型。但KEY分区的时候,可以使用其他类型的列(BLOB,TEXT类型除外)作为分区键。
(2)如果表中存在主键或者唯一索引的列,那么分区键中的列必须在主键或唯一索引中包括。否则会报错1503。
(3)一个表最多只能有1024个分区。
(4)分区表中无法使用外键约束。
(5)RANGE分区将null值放在范围最小的分区,LIST将其保存在0的分区;在按HASH和KEY分区的情况下,任何产生NULL值的表达式mysql都视同它的返回值为0。为了避免这种情况的产生,建议分区键设置成NOT NULL。

3、RANGE分区

(1)首先确认分区功能开启
MySQL从5.1版本开始支持分区,5.6以下的版本:

show variables like '%partition%

会出现have_partitioning YES。
5.6以上的版本

show plugins;


出现partition ACTIVE

(2)创建表

DROP TABLE IF EXISTS test;
CREATE TABLE test (id INT(11) NOT NULL AUTO_INCREMENT,uid INT(11) NOT NULL,name VARCHAR(30) NOT NULL,placeid INT(11) NOT NULL,salary FLOAT,PRIMARY KEY(id, placeid)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY RANGE (placeid)(PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11),PARTITION p2 VALUES LESS THAN (MAXVALUE)
);

注意这里,因为存在主键,所以用来分区的键必须包含在主键里。;less than不能出现无法区分的情况,不如出现两次less than (21)。
创建完成后,在mysql/data/separation目录下可以看到,

其中.par文件存储分区信息。
(3)插入数据

INSERT INTO test VALUES(1, 10001, '张三', 1, 5555.55);
INSERT INTO test VALUES(2, 10002, '李四', 3, 5555.55);
INSERT INTO test VALUES(3, 10003, '小六', 7, 6666.66);
INSERT INTO test VALUES(4, 10004, '王五', 13, 7000);
INSERT INTO test VALUES(5, 10005, '赵一', 24, 7000);

其中前两条会插入p0,第三条插入p1,后两条插入p2。
(4)根据时间划分
根据TIMESTAMP范围:

DROP TABLE IF EXISTS test_timestamp;
CREATE TABLE test_timestamp(id INT(11) NOT NULL,time TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY RANGE (UNIX_TIMESTAMP(time))(PARTITION p0 VALUES LESS THAN (UNIX_TIMESTAMP('2019-12-31 00:00:00')),PARTITION p1 VALUES LESS THAN (UNIX_TIMESTAMP('2020-05-12 00:00:00')),PARTITION p2 VALUES LESS THAN (MAXVALUE)
);

根据DATE、DATETIME范围:
添加COLUMNS关键字可以定义非INT类型,但是COLUMNS括号内只能是列名,不支持函数

DROP TABLE IF EXISTS test_date;
CREATE TABLE test_date(id INT(11) NOT NULL,time DATE
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY RANGE COLUMNS(time)(PARTITION p0 VALUES LESS THAN ('2019-12-31'),PARTITION p1 VALUES LESS THAN ('2020-05-12'),PARTITION p2 VALUES LESS THAN (MAXVALUE)
);

这里range(year(time))可以很方便的按年份分区。
(5)多列分区
COLUMNS关键字也可用于多列分区

DROP TABLE IF EXISTS test_columns;
CREATE TABLE test_columns (id INT(11) NOT NULL,uid INT(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY RANGE COLUMNS(id, uid)(PARTITION p0 VALUES LESS THAN (6, 10),PARTITION p1 VALUES LESS THAN (11, 20),PARTITION p2 VALUES LESS THAN (MAXVALUE, MAXVALUE)
);

注意这里每一列只能出现一次MAXVALUE,出现多次会报错1493。

4、LIST分区

和RANGE分区类似,不使用COLUMNS关键字时,只允许LIST括号内为INT类型或返回INT类型的函数。
假设国内城市的city_id为:1、3、7、11、19;国外城市的city_id为:5、10、20。

DROP TABLE IF EXISTS test_list;
CREATE TABLE test_list (id INT(11) NOT NULL,city_id INT(11)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY LIST (city_id)(PARTITION p_china VALUES IN (1, 3, 7, 11, 19),PARTITION p_foreign VALUES IN (5, 10, 20)
);

5、HASH分区

HASH分区主要用来确保数据在确定好的分区数目的分区中均匀分布,实际上就是将整数对分区数取模后确定分区。

DROP TABLE IF EXISTS test_hash;
CREATE TABLE test_hash (id INT(11) NOT NULL,city_id INT(11)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY HASH (city_id)
PARTITIONS 3;

HASH括号里可以是整数也可以是返回整数的表达式;“PARTITIONS num”表示要被分割成分区的数量,如果没有该语句,默认分区数量为1。
另外将HASH替换为LINEAR HASH:

PARTITION BY LINEAR HASH (city_id)

普通HASH(value)的计算过程比较简单是:value%num,但是其扩展性差。LINEAR HASH的计算过程:

(1)V = POWER(2, CEILING(LOG(2, num)))
这一步是找到第一个大于等于num的2的幂次整数;
POWER为指数计算,CEILINGL为向上取整运算,LOG为对数运算;
(2)N = value & (V-1), &为按位与操作;
(3)当N >= num:V = CEIL(V/2), N = N & (V-1), CEIL为向下取整操作。

线性哈希分区的好处是增加,下降,合并,拆分分区可以更快,有利于在处理含有非常大量的数据表(百万兆字节)。缺点是,与常规哈希分区获得的分布相比,分区之间不太可能均匀分布数据。

6、KEY分区

KEY分区和HASH分区相似,只需要将HASH分区的HASH换为KEY即可,区别是两者的哈希函数不同。KEY分区中同样可以使用LINEAR关键字。
另外当表存在主键或唯一索引时可省略Key括号内的列名,Mysql将按照主键-唯一索引的顺序选择,当找不到唯一索引时报错1488。

DROP TABLE IF EXISTS test_key;
CREATE TABLE test_key (id INT(11) NOT NULL PRIMARY KEY,city_id INT(11)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY KEY ()
PARTITIONS 3;

7、性能比较

以range分区为例,采用range分区中(2)(3)创建的数据表test,未分区前,查询placeid = 13的数据,可以看到搜索了5条数据,

而添加分区后,由于placeid = 13只可能存在于分区p2中,所以只需要搜索p2分区,搜索2条数据即可。现在因为数据量少差距不大,当数据量很大时,分区能够带来很大程度的性能提升。

8、分区的管理

以range分区为例,采用range分区中(2)(3)创建的数据表test。
(1)增加分区

ALTER TABLE test ADD PARTITION (PARTITION p3 VALUES LESS THAN (100));

(2)删除分区

ALTER TABLE test DROP PARTITION p0;

删除分区同时删除该分区数据;不可删除HASH分区和KEY分区。
(3)删除全部分区

Alter TABLE test REMOVE PARTITIONING;

只清除所有分区,保留数据。
(4)修改分区

ALTER TABLE test PARTITION BY RANGE (placeid)(PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11),PARTITION p2 VALUES LESS THAN (16),PARTITION p3 VALUES LESS THAN (MAXVALUE)
);

若修改的是HASH分区或者KEY分区:

ALTER TABLE test_hash PARTITION BY HASH(city_id)PARTITIONS 7;

(5)拆分分区

ALTER TABLE test
REORGANIZE PARTITION p0 INTO
(
PARTITION p0_1 VALUES LESS THAN (3),
PARTITION p0_2 VALUES LESS THAN (6)
);

注意拆分后的总范围应保持拆分前的范围保持一致。
(6)合并分区

ALTER TABLE test
REORGANIZE PARTITION p0_1,p0_2 INTO
(
PARTITION p0 VALUES LESS THAN (6)
);

同样需要注意合成后的范围应该和合成前各分区的总范围一致。
(7)重建分区

ALTER TABLE test REBUILD PARTITION p0,p1;

此操作和先删除保存在分区的数据,然后重新插入它们具有相同的效果,可以用来整理分区碎片。
(8)优化分区

ALTER TABLE test OPTIMIZE PARTITION p0,p1;

如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB,或TEXT类型的列)作了许多修改,该操作可用来回收没有使用的空间,并整理分区数据文件碎片。

和(7)(8)操作类似的还有:

ALTER TABLE test ANALYZE PARTITION p0,p1;   -- 分析分区
ALTER TABLE test REPAIR PARTITION p0,p1;   -- 修补分区
ALTER TABLE test CHECK PARTITION p0,p1;   -- 检查分区

数据库分区:MySQL分区相关推荐

  1. MySQL数据库分表分区

    防伪码:当你终于沉默,成熟才刚刚开始. 为什么要分表和分区? 我们的数据库数据越来越大,随之而来的是单个表中数据太多.以至于查询书读变慢,而且 由于表的锁机制导致应用操作也搜到严重影响,出现了数据库性 ...

  2. mysql数据库建新分区_mysql数据库分区

    日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会更加糟糕.分表和表分 ...

  3. mysql数据库表分区_MySQL数据库之MySQL的分区和分表详解

    本文主要向大家介绍了MySQL数据库之MySQL的分区和分表详解 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. 1. 分区 MySQL中的分区是指将一个数据表按照某种规则(如时 ...

  4. mysql partition 语法,MySQL与瀚高数据库的范围分区的语法及实例(APP)

    目录 环境 文档用途 详细信息 环境 系统平台:Microsoft Windows (64-bit) 10 版本:5.6.4 文档用途 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就 ...

  5. Mysql数据库调优——分区

    Mysql数据库调优--分区 参考资料: MySQL分区:https://www.bilibili.com/video/BV1E7411q7Nx MySQL_基础+高级篇- 数据库 -sql -mys ...

  6. MySQL数据库表的分区

    分区的过程是将一个表或索引分解为多个更小.更可管理的部分.就访问数据库的应用而言,从逻辑上讲,只有一个表或索引,但是在物理上这个表或索引可能由数十个物理分区组成.每个分区都是独立的对象,可以独自处理, ...

  7. mysql数据库索引 分区_数据库设计 – 要索引的列太多 – 使用mySQL分区?

    我不是 MySQL专家.我的重点是Oracle,但我一直在使用分区多年,我发现你的建议用途非常合适,但不是主流对分区的理解. 低基数列的索引 暂且不谈索引合并.假设您的活动行有点分散,并且与非活动行数 ...

  8. 第18章:MYSQL分区

    第18章:分区 目录 18.1. MySQL中的分区概述18.2. 分区类型 18.2.1. RANGE分区18.2.2. LIST分区18.2.3. HASH分区18.2.4. KEY分区18.2. ...

  9. mysql 分区_搞懂MySQL分区

    一.InnoDB逻辑存储结构 首先要先介绍一下InnoDB逻辑存储结构和区的概念,它的所有数据都被逻辑地存放在表空间,表空间又由段,区,页组成. 段 段就是上图的segment区域,常见的段有数据段. ...

最新文章

  1. Lua 生成凌晨与午夜时间戳的函数
  2. CTFshow 反序列化 web255
  3. pythonpandas设置索引_python – pandas:使用(row,col)索引设置值
  4. 2014-02-20
  5. js正则表达式test()和exec()用法
  6. RabbitMQ的消息确认ACK机制
  7. 只用html5与CSS做一个简单的页面,HTML+CSS基础训练之做一个简单页面的布局
  8. 【Java】JavaIO(一)、基础知识
  9. dj鲜生-用户中心-历史购物
  10. 使用英文做LDA建模
  11. android 使用注解
  12. DataTable随机复制一行给新的DataTable
  13. 剑指Offer之寻找链表倒数第k个节点
  14. 行测题练习(7-29)【1】
  15. 图片隐写,盲水印,加密logo
  16. 如何将iPhone核心数据与Web服务器同步,然后推送到其他设备? [关闭]
  17. 物联平台纷争,能否拯救智能硬件?
  18. 什么是集合?集合的相关知识
  19. Jmeter使用教学
  20. pg日期转周_PostgreSQL 日期/时间类型

热门文章

  1. MySQL千万级别表数据中提高RAND随机查询的实验
  2. 【hive-3.1.3】ORC 格式的表和 text 格式的表,当分区的字段数量和表的字段数量不一致,检索结果不相同
  3. ikeas电子商务在covid 19时期就已经很糟糕了,它绝对崩溃了
  4. C compiler cannot create executables问题
  5. 【剑指 Java】第 1 弹:靠这份 Java 基础知识总结,我拿到了满意的 Offer
  6. 搭建私有云maven文档(超详细)超级容易上手
  7. POJ - 2955 Brackets (区间DP)
  8. 计算机术语位字节字字长分别是什么,字长、字节、字、字位的区别
  9. 尼康D780相机黑屏的故障原因
  10. 真c++ 从二叉树到红黑树(6)之红黑树RedBlack