MySQL 分区知识点(一 )
前言:
查了下资料,关于 MySQL 分区的博文讲的详细的比较少,也不全,只好在官网去翻译英文文章看了。大体整理了一下记录起来;
MySQL 分区类型:
1、RANGE 分区;
// 这种类型的分区基于落在给定范围内的列值将行分配给分区。
2、LIST 分区;
// 与 RANGE 分区类似,除了根据匹配一组离散值之一的列来选择分区。
3、COLUMNS 分区;
// 提供对 LIST COLUMNS 分区的支持。这是一种LIST分区的变体 ,可以使用多列作为分区键,
也可以使用不同于整数类型的数据类型列作为分区列; 您可以使用字符串类型 DATE和 DATETIME列。
4、HASH 分区;
// 使用这种类型的分区,将根据用户定义的表达式返回的值来选择分区,该表达式对要插入到表中的行中的列值进行操作。
该函数可以由在 MySQL 中有效的表达式产生非负整数值的任何表达式组成。此类型的扩展 LINEAR HASH 也可用。
5、KEY 分区;
// HASH 除了只提供一个或多个要评估的列,MySQL 服务器提供了自己的散列函数之外, 这种类型的分区类似于分区 。
这些列可以包含除整数值之外的列,因为 MySQL 提供的散列函数保证整数结果,
而不管列数据类型如何。此类型的扩展 LINEAR KEY 也可用。
6、Subpartitioning 分区;(子分区)
// 子分区(也称为 复合分区)是分区表中每个分区的进一步划分。
一、RANGE 分区
按范围分区的表以每个分区包含分区表达式值位于给定范围内的行分配。
范围应该是连续的,但不重叠,并且使用 VALUES LESS THAN 运算符定义 。
接下来的几个例子,假设您正在创建一个如下所示的表,以容纳 20 个视频存储区的人员记录,编号为1到20:
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 NOT NULL, store_id INT NOT NULL ) PARTITION BY RANGE (store_id) ( PARTITION p0 VALUES LESS THAN (6), PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16), PARTITION p3 VALUES LESS THAN MAXVALUE );
在这种分区方案中,对应于在存储1到5工作的员工的所有行都存储在分区中p0,存储在 存储器6到10中的那些被存储在分区中p1,依此类推;
每个分区按顺序定义,从最低到最高。这是PARTITION BY RANGE语法的要求;
MAXVALUE表示总是大于最大可能整数值的整数值(以数学语言,它用作 最小上限);
// 也可以采用日期、等范围进行分区;
二、LIST 分区
MySQL中的列表分区在很多方面类似于范围分区。在分区时RANGE
,必须明确定义每个分区。
两种类型的分区之间的主要区别在于,在列表分区中,每个分区根据一组值列表中的一列中的列值的成员资格而不是一组连续范围值。
这是通过使用完成,其中 是基于列值的列值或者表达式并返回一个整数值,然后通过的手段限定每个分区 ,其中 是用逗号分隔的整数列表。
语法:PARTITION BY LIST(
expr
)expr
VALUES IN (
value_list
)value_list
举例:假设在4个特许经营店中分配了20个视频商店,要以这样的方式对属于同一区域的商店的行存储在同一个分区中的方式进行分区;
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 LIST(store_id) ( PARTITION pNorth VALUES IN (3,5,6,9,17), PARTITION pEast VALUES IN (1,2,10,11,19,20), PARTITION pWest VALUES IN (4,12,13,14,18), PARTITION pCentral VALUES IN (7,8,15,16) );
这样可以轻松地将与表中特定区域相关的员工记录添加或删除。例如,假设西部地区的所有商店都被卖给另一家公司。
在该区域的商店工作的员工相关的所有行都可以通过查询删除 ALTER TABLE employees TRUNCATE PARTITION pWest
,
这可以比等效 DELETE 语句更有效地执行 DELETE FROM employees WHERE store_id IN (4,12,13,14,18);
。
(使用ALTER TABLE employees DROP PARTITION pWest
也会删除所有这些行,但也会pWest
从表的定义中删除分区 ;
您需要使用ALTER TABLE ... ADD PARTITION
语句来还原表的原始分区方案。)
与RANGE
分区一样,可以LIST
通过哈希或密钥将分区与分区组合以产生复合分区(子分区)。
// 如果插入不在 LIST 分区范围内的 id,者会报错:ERROR 1525 (HY000): Table has no partition for value 3
三、COLUMNS 分区
所谓 COLUMNS 分区就是 RANGE COLUMNS 分区和 LIST COLUMNS 分区两种,在 RANGE、LIST 的基础上做的扩充;
RANGE CLOUMNS:
RANGE CLOUMNS 分区和 RANGE 分区类似,但可以使用基于多个列值的范围来定义分区。
此外,还可以使用除整数类型之外的类型的列定义范围。
RANGE COLUMNS
分区与RANGE
以下方式显着不同:
#、RANGE COLUMNS
不接受表达式,只接受列的名称;
#、RANGE COLUMNS
接受一个或多个列的列表;
RANGE COLUMNS
分区基于元组(列值列表)之间的比较,而不是标量值之间的比较;
RANGE COLUMNS
分区中行的放置也是基于元组之间的比较;
#、RANGE COLUMNS
分区列不限于整数列;字符串、DATE 和 DATETIME
列也可以用作分区列;
CREATE TABLE rcx ( a INT, b INT, c CHAR(3), d INT ) PARTITION BY RANGE COLUMNS(a,d,c) ( PARTITION p0 VALUES LESS THAN (5,10,'ggg'), PARTITION p1 VALUES LESS THAN (10,20,'mmm'), PARTITION p2 VALUES LESS THAN (15,30,'sss'), PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE) );
// 一般用的不会太多,不做太多了解,详情见:
https://dev.mysql.com/doc/refman/8.0/en/partitioning-columns-range.html
LIST COLUMNS:
这是一种LIST
分区的变体 ,可以使用多列作为分区键,也可以使用不同于整数类型的数据类型列作为分区列;
举例:
假设您有一个在12个城市有客户的业务,出于销售和营销目的,您可以组织到3个城市的4个地区;
CREATE TABLE customers_1 ( first_name VARCHAR(25), last_name VARCHAR(25), street_1 VARCHAR(30), street_2 VARCHAR(30), city VARCHAR(15), renewal DATE ) PARTITION BY LIST COLUMNS(city) ( PARTITION pRegion_1 VALUES IN('Oskarshamn', 'Hogsby', 'Monsteras'), PARTITION pRegion_2 VALUES IN('Vimmerby', 'Hultsfred', 'Vastervik'), PARTITION pRegion_3 VALUES IN('Nassjo', 'Eksjo', 'Vetlanda'), PARTITION pRegion_4 VALUES IN('Uppvidinge', 'Alvesta', 'Vaxjo') );
// 甚至在分区中可以使用这种的语法:PARTITION pWeek_1 VALUES IN('2010-02-01', '2010-02-02', '2010-02-03'); pWeek 为 DATE 数据类型;
四、HASH 分区
HASH 分区主要用于确保在预定数量的分区之间均匀分配数据;基于分区个数的取模(%)运算。根据余数插入到指定的分区;
要使用分区对表进行HASH
分区,需要在 CREATE TABLE 语句附加一个子句,其中是返回一个整数的表达式。
这可以只是一个列的名称,其类型是MySQL的整数类型之一。
此外,您最有可能希望遵循这一点,其中 是一个正整数,表示要分割表的分区数。
语法:PARTITION BY HASH (
expr
) expr
PARTITIONS
num
num
以下语句创建一个表,该store_id
列在列上使用散列, 并分为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(store_id) PARTITIONS 4;
线性 HASH 分区:(没能明白,官方地址)
https://dev.mysql.com/doc/refman/8.0/en/partitioning-linear-hash.html
五、KEY 分区
按 键 划分类似于通过哈希分区,除了哈希分区采用用户定义的表达式之外,密钥分区的哈希函数由 MySQL 服务器提供。
语法:CREATE TABLE ... PARTITION BY KEY
类似于用于创建由哈希分区的表的语法规则。主要区别如下:
#、KEY
被使用而不是 HASH;
#、KEY
仅列出零个或多个列名称。用作分区键的任何列必须包含表的主键的一部分或全部,如果该表具有一个。
如果没有列名称作为分区键,则使用表的主键(如果有)。
CREATE TABLE k1 ( id INT NOT NULL PRIMARY KEY, name VARCHAR(20) ) PARTITION BY KEY() PARTITIONS 2;
必须定在主键之上,如果没有主键定义在唯一键列上,同理不允许为 NULL;
六、Subpartitioning 分区
子分区(也称为 复合分区)是分区表中每个分区的进一步划分。
举例:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) SUBPARTITIONS 2 ( PARTITION p0 VALUES LESS THAN (1990), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE );
表 ts 有 3 个 RANGE 分区。这些分区-中的每一个 p0,p1和 p2-is 进一步分成2子分区。实际上,整个表分为几个 3 * 2 = 6分区。
但是,由于该 PARTITION BY RANGE 条款的作用,其中的前 2 个仅存储该 purchased 列中值小于1990的那些记录。
可以由 RANGE
或分隔的子分区表 LIST
。子分区可以使用 HASH
或 KEY
分区。这也称为 复合分区。
也可以使用SUBPARTITION
子句明确定义子部分 来指定各个子分区的选项。
举例:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s2, SUBPARTITION s3 ) );
// 参考自 MySQL 官网