阅读innodb分区文档
This commit is contained in:
@@ -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 |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user