阅读innodb分区文档

This commit is contained in:
asahi
2025-02-09 22:20:26 +08:00
parent 6b5e042d3d
commit 130714fe74

View File

@@ -408,3 +408,209 @@ select * from t1;
| 1 | 2023-01-01 00:00:00.000000 | | 1 | 2023-01-01 00:00:00.000000 |
| 2 | 2024-12-31 00:00:00.000000 | | 2 | 2024-12-31 00:00:00.000000 |
| 3 | 2025-01-01 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 |