>分区是指根据一定的规则, 数据库把表分解成更多个更小的, 更容易管理的部分,就访问数据库的应用而言, 逻辑上只有一个表或一个索引,但实际上这个表可以由多个物理分区对象组成,每个分区都有一个独立的对象,可以独自处理, 可以作为表的一部分进行处理。分区对于应用来说是透明的, 不影响应用的业务逻辑。
> 分区的有点有4:
1. 和单个磁盘或文件系统分区相比, 可以存储更多数据
2. 优化查询, 在WHERE字句中包含分区条件时,可以只扫描必要的一个或多个分区来提高查询效率,同时涉及到SUM()和Count()这类聚合函数的查询时,可以容易地在每个分区上并行处理, 最终只需要汇总所有的分区得到结果。
3. 对于已经过期的或者不需要的数据, 我们只需要删除对应发分区即可。
4. 跨多个磁盘来分散数据查询, 以获取更大的查询吞吐量
判断数据库是否支持分区操作:
mysql> show variables like '%partition%';
+---------------------------------------+-------+
| Variable_name | Value |
+---------------------------------------+-------+
| innodb_adaptive_hash_index_partitions | 1 |
+---------------------------------------+-------+
1 row in set (0.03 sec)
//但是这里存在一个问题, 在另一个数据中使用同样的命令, 得到的结果却是:
mysql> show variables like '%partition%';
Empty set (0.01 sec)
//然而在该数据库中依旧支持分区操作
分区类别:
- RANGE:基于给定的连续区间范围, 把数据分配到不同的分区
- LIST:类似RANGE分区, 区别在于LIST分区基于枚举出的值列表分区, RANGE是基于给定的连续空间范围分区
- HASH:给定分区数量, 数据库会自动将不同数据分配到不同的分区中的
- KEY:类似HASH分区
RANGE
对应RANGE类型的分区来说, 容易拓展, 但是不利于调整, 例如:
CREATE TABLE `rangePartition` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(124) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (3) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (5) ENGINE = InnoDB) */ |
//对应该表来说如果需要拓展出新的分区来说是容易的, 但是如果发现之前的分区分配是不合理的,那么需要调整就不是那么容易了。
alter table rangePartition add partition (partition p2 values less than (7));
Query OK, 0 rows affected (0.16 sec)
Records: 0 Duplicates: 0 Warnings: 0
LIST
| listPartition | CREATE TABLE `listPartition` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (id)
(PARTITION p0 VALUES IN (1,2,4) ENGINE = InnoDB,
PARTITION p1 VALUES IN (3,5) ENGINE = InnoDB) */ |
mysql> select * from listPartition;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 3 | 3 |
| 5 | 5 |
+----+------+
//这时可以发现, 查询是以分区来查询, 并不是根据插入的顺序显示
//当插入的数据不在任何一个分区中时, 数据库会提示错误
mysql> insert into listPartition(name) values ('6');
ERROR 1526 (HY000): Table has no partition for value 6
COLUMNS
//columens range 分区是mysql5.5引出的, columns 分区解决
//之前range分区和list分区只支持整数分区,从而导致需要额外的
//函数或者通过额外的转换表来转换为整数再分区的问题。columns
//分区分为RANGE columns 和 list columns, 他们都支持整
//数, 日期, 字符串三大数据类型。
| columnsRangePartition | CREATE TABLE `columnsRangePartition` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE COLUMNS(a,b)
(PARTITION p0 VALUES LESS THAN (0,10) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (10,10) ENGINE = InnoDB) */ |
//分区方式(a < 0 OR (a=10 And b<10))
HASH
hash 分区只需要明确做多少个分区即可,hash 分区允许用户自定义表达式
| hashPartition | CREATE TABLE `hashPartition` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (id)
PARTITIONS 5 */ |
KEY
key分区不允许用户自定表达式
| hashPartition | CREATE TABLE `keyPartition` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY key (name)
PARTITIONS 5 */ |