介绍
Mysql5.5只支持水平分区,还不支持垂直分区。
MySQL分区不能与使用 MERGE,CSV或 FEDERATED存储引擎。
分区适用于表的所有数据和索引; 您不能只分区数据而不分区索引,反之亦然,也不能只分区表的一部分。
通过分区,可以在一个表中存储比在单个磁盘或文件系统分区上保存的数据更多的数据。
查看当前数据库是否支持分区功能
查看当前数据库版本:
mysql> status
--------------
mysql Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using EditLine wrapper
Connection id: 25
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.7.24-log MySQL Community Server (GPL)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: latin1
Conn. characterset: latin1
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 3 days 23 hours 15 min 58 sec
Threads: 1 Questions: 167 Slow queries: 0 Opens: 125 Flush tables: 2 Open tables: 17 Queries per second avg: 0.000
--------------
查看当前数据库是否支持分区:
mysql> show plugins;
+----------------------------+----------+--------------------+----------------------+---------+
| Name | Status | Type | Library | License |
+----------------------------+----------+--------------------+----------------------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_PER_INDEX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_PER_INDEX_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_TEMP_TABLE_INFO | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_METRICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_BEING_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_CONFIG | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_INDEX_CACHE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_INDEX_TABLE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_TABLES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_TABLESTATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_COLUMNS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_FIELDS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_FOREIGN | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_FOREIGN_COLS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_DATAFILES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_VIRTUAL | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ngram | ACTIVE | FTPARSER | NULL | GPL |
| validate_password | ACTIVE | VALIDATE PASSWORD | validate_password.so | GPL |
+----------------------------+----------+--------------------+----------------------+---------+
45 rows in set (0.00 sec)
RANGE分区
确定行数据在某个给定连续区间的列值。然后放入该分区。
CREATE TABLE pt_range(
id int(16) unsigned NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL,
pwd VARCHAR(32) NOT NULL,
create_date datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) PARTITION BY RANGE(id) (
PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20),
PARTITION p2 VALUES LESS THAN (30),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
INSERT INTO pt_range(id, username, pwd, create_date)
VALUES (1, '张三', '123456', NOW()),
(2, '李四', '123456', NOW()),
(11, '张三', '123456', NOW()),
(21, '张三', '123456', NOW()),
(31, '张三', '123456', NOW());
查看分区中的各个分区文件:
mysql> system ls -lh /var/lib/mysql/sunpy/pt*
-rw-r----- 1 mysql mysql 96K Jan 16 11:38 /var/lib/mysql/sunpy/pt_range#P#p0.ibd
-rw-r----- 1 mysql mysql 96K Jan 16 11:36 /var/lib/mysql/sunpy/pt_range#P#p1.ibd
-rw-r----- 1 mysql mysql 96K Jan 16 11:36 /var/lib/mysql/sunpy/pt_range#P#p2.ibd
-rw-r----- 1 mysql mysql 96K Jan 16 11:36 /var/lib/mysql/sunpy/pt_range#P#p3.ibd
-rw-r----- 1 mysql mysql 8.5K Jan 16 11:21 /var/lib/mysql/sunpy/pt_range.frm
查看information_schema的PARTITIONS表下的每个分区的具体信息:
mysql> select * from information_schema.PARTITIONS WHERE table_schema=database() and table_name='pt_range'\G;
*************************** 1. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: sunpy
TABLE_NAME: pt_range
PARTITION_NAME: p0
SUBPARTITION_NAME: NULL
PARTITION_ORDINAL_POSITION: 1
SUBPARTITION_ORDINAL_POSITION: NULL
PARTITION_METHOD: RANGE
SUBPARTITION_METHOD: NULL
PARTITION_EXPRESSION: id
SUBPARTITION_EXPRESSION: NULL
PARTITION_DESCRIPTION: 10
TABLE_ROWS: 2
AVG_ROW_LENGTH: 8192
DATA_LENGTH: 16384
MAX_DATA_LENGTH: NULL
INDEX_LENGTH: 0
DATA_FREE: 0
CREATE_TIME: 2019-01-16 11:21:27
UPDATE_TIME: 2019-01-16 11:38:33
CHECK_TIME: NULL
CHECKSUM: NULL
PARTITION_COMMENT:
NODEGROUP: default
TABLESPACE_NAME: NULL
*************************** 2. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: sunpy
TABLE_NAME: pt_range
PARTITION_NAME: p1
SUBPARTITION_NAME: NULL
PARTITION_ORDINAL_POSITION: 2
SUBPARTITION_ORDINAL_POSITION: NULL
PARTITION_METHOD: RANGE
SUBPARTITION_METHOD: NULL
PARTITION_EXPRESSION: id
SUBPARTITION_EXPRESSION: NULL
PARTITION_DESCRIPTION: 20
TABLE_ROWS: 1
AVG_ROW_LENGTH: 16384
DATA_LENGTH: 16384
MAX_DATA_LENGTH: NULL
INDEX_LENGTH: 0
DATA_FREE: 0
CREATE_TIME: 2019-01-16 11:21:27
UPDATE_TIME: 2019-01-16 11:36:14
CHECK_TIME: NULL
CHECKSUM: NULL
PARTITION_COMMENT:
NODEGROUP: default
TABLESPACE_NAME: NULL
*************************** 3. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: sunpy
TABLE_NAME: pt_range
PARTITION_NAME: p2
SUBPARTITION_NAME: NULL
PARTITION_ORDINAL_POSITION: 3
SUBPARTITION_ORDINAL_POSITION: NULL
PARTITION_METHOD: RANGE
SUBPARTITION_METHOD: NULL
PARTITION_EXPRESSION: id
SUBPARTITION_EXPRESSION: NULL
PARTITION_DESCRIPTION: 30
TABLE_ROWS: 1
AVG_ROW_LENGTH: 16384
DATA_LENGTH: 16384
MAX_DATA_LENGTH: NULL
INDEX_LENGTH: 0
DATA_FREE: 0
CREATE_TIME: 2019-01-16 11:21:27
UPDATE_TIME: 2019-01-16 11:36:14
CHECK_TIME: NULL
CHECKSUM: NULL
PARTITION_COMMENT:
NODEGROUP: default
TABLESPACE_NAME: NULL
*************************** 4. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: sunpy
TABLE_NAME: pt_range
PARTITION_NAME: p3
SUBPARTITION_NAME: NULL
PARTITION_ORDINAL_POSITION: 4
SUBPARTITION_ORDINAL_POSITION: NULL
PARTITION_METHOD: RANGE
SUBPARTITION_METHOD: NULL
PARTITION_EXPRESSION: id
SUBPARTITION_EXPRESSION: NULL
PARTITION_DESCRIPTION: MAXVALUE
TABLE_ROWS: 1
AVG_ROW_LENGTH: 16384
DATA_LENGTH: 16384
MAX_DATA_LENGTH: NULL
INDEX_LENGTH: 0
DATA_FREE: 0
CREATE_TIME: 2019-01-16 11:21:27
UPDATE_TIME: 2019-01-16 11:36:14
CHECK_TIME: NULL
CHECKSUM: NULL
PARTITION_COMMENT:
NODEGROUP: default
TABLESPACE_NAME: NULL
4 rows in set (0.00 sec)
LIST分区
与分区相似RANGE,只是LIST分区面向的是离散的值。
CREATE TABLE pt_list(
id int(16) unsigned NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL,
pwd VARCHAR(32) NOT NULL,
create_date datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) PARTITION BY LIST(id) (
PARTITION p0 VALUES IN (1, 3, 5, 7, 9),
PARTITION p1 VALUES IN (2, 4, 6, 8, 10)
);
HASH分区
根据用户自定义的表达式的返回值来进行分区,返回值不能为负数。
CREATE TABLE pt(
id int(16) unsigned NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL,
pwd VARCHAR(32) NOT NULL,
create_date datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) PARTITION BY HASH(id) PARTITIONS 4;
KEY分区
根据mysql提供的hash函数来进行分区。
CREATE TABLE pt_key(
id int(16) unsigned NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL,
pwd VARCHAR(32) NOT NULL,
create_date datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) PARTITION BY KEY(id) PARTITIONS 2;
说明:KEY仅获取零个或多个列名称的列表。用作分区键的任何列必须包含表的主键的部分或全部,如果表有一个。如果没有将列名指定为分区键,则使用表的主键(如果有)。
分区操作
- 添加分区
ALTER TABLE pt_range ADD PARTITION (PARTITION p4 VALUES LESS THAN (2019));
- 删除分区
ALTER TABLE pt_range DROP PARTITION p4;
注意
- 删除分区的同时也会删除分区中的数据。
- 如果分区字段中必须包含所有的唯一索引列。
- 分区表达式不允许使用存储过程或存储函数。
- 分区表达式不允许使用声明的用户变量等。
- 分区的InnoDB不支持外键。
- RANGE分区对于Null值是存储在最左边的分区中。
- LIST分区对于Null值是必须显式指定在哪个分区,要不报错。
分区好处
我们知道分区特点就是将数据按照一定规则放到不同的区域中,而查询数据会先找数据放在哪个区域下,减少了无用的行记录的扫描。