diff --git a/mysql/mysql文档/mysql_表.md b/mysql/mysql文档/mysql_表.md index 947b72a..4545c0a 100644 --- a/mysql/mysql文档/mysql_表.md +++ b/mysql/mysql文档/mysql_表.md @@ -408,3 +408,209 @@ select * from t1; | 1 | 2023-01-01 00:00:00.000000 | | 2 | 2024-12-31 00:00:00.000000 | | 3 | 2025-01-01 00:00:00.000000 | + +#### LIST +LIST分区类型和RANGE分区类型非常相似,但是LIST分区列的值是离散的,RANGE分区列的值是连续的。 + +创建LIST类型分区表的示例如下: +```sql +create table p_list_t1 ( + id bigint not null auto_increment, + area smallint not null, + primary key (id, area) +) +partition by list (area) ( + partition p_ch_beijing values in (1), + partition p_ch_hubei values in (2), + partition p_ch_jilin values in (3) + ); +``` +之后可向`p_list_t1`表中预置数据,执行语句如下: +```sql +insert into p_list_t1(area) values (1),(1), (2), (3), (3); +``` +此时,数据分布如下: +| PARTITION\_METHOD | PARTITION\_NAME | TABLE\_ROWS | +| :--- | :--- | :--- | +| LIST | p\_ch\_beijing | 2 | +| LIST | p\_ch\_hubei | 1 | +| LIST | p\_ch\_jilin | 2 | + +如果想要向分区表中插入不位于现存分区中的值,那么插入语句同样会执行失败,示例如下 +```sql +insert into p_list_t1(area) values (4); +``` +由于目前没有area为4的分区,故而插入语句执行失败,报错如下 +```bash +[2025-02-09 20:30:03] [HY000][1526] Table has no partition for value 4 +``` + +#### HASH +HASH分区方式是将数据均匀分布到预先定义的各个分区中,期望各个分区中散列的数据数量大致相同。 + +在通过hash来进行分区时,建表时需要指定一个分区表达式,该表达式返回整数。 + +创建hash分区的示例如下: +```sql +create table p_hash_t1 ( + id bigint not null auto_increment, + content varchar(256), + primary key (id) +) +partition by hash (id) +partitions 4; +``` +上述ddl创建了一个按照`id`列进行hash分区的分区表,分区表包含4个分区。 + +预置数据sql如下: +```sql +insert into p_hash_t1(content) values ('asahi'), ('maki'), ('katahara'); +``` +预置数据后数据分布如下 +| PARTITION\_METHOD | PARTITION\_NAME | TABLE\_ROWS | +| :--- | :--- | :--- | +| HASH | p0 | 0 | +| HASH | p1 | 1 | +| HASH | p2 | 1 | +| HASH | p3 | 1 | + +预置的三条数据id分别为`1, 2, 3`,被hash放置到分区`p1, p2, p3`中。 + +> 当使用hash分区方式时,例如存在`4`个分区,对于待插入数据其分区表达式的值为`2`,那么待插入数据将会被插入到`2%4 = 2`,第`3`个分区中(0,1,2分区,排第三),也就是`p2`。 +> +> 可以通过`explain select * from p_hash_t1 where id = 2;`语句来进行验证,得到如下结果。 +> +> | id | select\_type | table | partitions | type | possible\_keys | key | key\_len | ref | rows | filtered | Extra | +> | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | +> | 1 | SIMPLE | p\_hash\_t1 | p2 | const | PRIMARY | PRIMARY | 8 | const | 1 | 100 | null | + + +##### 新增HASH分区 +对于hash分区方式,可以通过如下方式来新增分区: +```sql +alter table p_hash_t1 add partition partitions 3; +``` +其会新增3个分区,执行后分区数量为7。 + +此时,原本分区中的数据会被重新散列到新分区中 + +##### 减少HASH分区 +对于hash分区,在尝试减少分区数量的同时,通常不希望删除任何数据,故而无法使用`drop`。 + +故而,可以使用`coalesce`,其只会减少分区数量,不会删除数据。 + +示例如下: +```sql +alter table p_hash_t1 coalesce partition 4; +``` +上述语句会将分区数量减少4个,故而减少后分区数量为`3`。 + + +#### LINEAR HASH +创建linear hash分区表的方式和hash类似,可以通过如下方式 +```sql +create table p_linear_hash_t1 ( + id bigint not null auto_increment, + content varchar(256), + primary key(id) +) +partition by linear hash (id) +partitions 5; +``` +相较于hash分区,在使用linear hash分区时,添加、删除、合并、拆分分区将会变得更加快捷,但是相比于hash分区,其数据分区可能会不太均匀。 + +#### KEY & LINEAR KEY +KEY分区方式和HASH分区方式类似,但是HASH分区采用用户自定义的函数进行分区,而KEY分区方式则是采用mysql提供的函数进行分区。 + +创建key分区表的示例如下: +```sql +create table p_key_t1 ( + id bigint not null auto_increment, + content varchar(256), + primary key(id) +) +partition by key(id) +partitions 5; +``` +> key分区方式同样可以使用linear进行修饰,效果和hash分区方式类似。 + +> 对于key分区,可以指定除了integer之外的col类型,而`range, list, hash`等分区类型只支持integer类型的col。 + + +#### COLUMNS +COLUMNS分区方式为`RANGE`和`LIST`分区的变体。 + +COLUMNS分区方式支持在分区时使用多个列,在插入新数据或查询数据决定分区时,所有的列都会被考虑。 + +COLUMNS分区方式分为如下两种 +- RANGE COLUMNS +- LIST COLUMNS + +上述两种方式都支持非整数类型的列,COLUMNS支持的数据类型如下: +- 所有integers类型(DECIMAL, FLOAT则不受支持) +- DATE和DATETIME类型 +- 字符串类型:CHAR, VARCHAR, BINARY, VARBINARY(TEXT, BLOB类型不受支持) + +##### range columns +创建range columns分区表的示例如下: +```sql +create table p_range_columns_t1 ( + id bigint not null auto_increment, + name varchar(256), + born_ts datetime(6), + primary key (id, born_ts) +) +partition by range columns (born_ts) ( + partition p0 values less than ('1900-01-01'), + partition p1 values less than ('2000-01-01'), + partition p2 values less than ('2999-01-01') + ); +``` + +##### list columns +创建list columns分区表的示例则如下: +```sql +create table p_list_columns_t1 ( + id bigint not null auto_increment, + province varchar(256), + city varchar(256), + primary key (id, province, city) +) +partition by list columns (province, city) ( + partition p_beijing values in (('china', 'beijing')), + partition p_wuhan values in (('hubei', 'wuhan')) + ); +``` + +> 通过range columns和list columns,可以很好的替代range和list分区,而无需将列值都转换为整型。 + +### 子分区 +`子分区`代表在分区的基础上再次进行分区,mysql允许`在range和list分区的基础`上再次进行`hash或key`的子分区,示例如下: +```sql +create table p_list_columns_t1 ( + id bigint not null auto_increment, + province varchar(256), + city varchar(256), + primary key (id, province, city) +) +partition by list columns (province, city) +subpartition by key(id) +subpartitions 3 +( + partition p_beijing values in (('china', 'beijing')), + partition p_wuhan values in (('hubei', 'wuhan')) +); +``` +上述示例先按照`list columns`分区方式进行了分区,然后在为每个分区都按`key`分了三个子分区,查看分区和子分区详情可以通过如下语句: +```sql +select partition_name, partition_method, subpartition_name, subpartition_method from information_schema.partitions where table_name = 'p_list_columns_t1'; +``` +| PARTITION\_NAME | PARTITION\_METHOD | SUBPARTITION\_NAME | SUBPARTITION\_METHOD | +| :--- | :--- | :--- | :--- | +| p\_wuhan | LIST COLUMNS | p\_wuhansp0 | KEY | +| p\_wuhan | LIST COLUMNS | p\_wuhansp1 | KEY | +| p\_wuhan | LIST COLUMNS | p\_wuhansp2 | KEY | +| p\_beijing | LIST COLUMNS | p\_beijingsp0 | KEY | +| p\_beijing | LIST COLUMNS | p\_beijingsp1 | KEY | +| p\_beijing | LIST COLUMNS | p\_beijingsp2 | KEY | +