目录
首先查看MySQL是否支持分区
在实际操作分区前我们得了解下分区的几点限制:
RANGE分区实操
SQL如何查询分区数据
首先查看MySQL是否支持分区
show plugins;
当查询结果显示partition的状态为active则表示当前MySQL版本支持分区。分区方案一般有四种:
- RANGE分区:RANGE分区主要用于日期列的分区,是基于连续区间的列值来进行分区的。RANGE分区也是最常用的分区方式。
- LIST分区:LIST分区列的值是散列的,也正是由于分区列的值是散列的所以需要手动定义分区列的值。
- HASH分区:HASH分区就是通过自定义算法将数据均匀分布到不同分区,保证所有分区中数据大致相同。HASH分区只支持整数分区。
- KEY分区:key分区使用数据库自带函数进行分区。KEY分区可支持BLOB和TEXT列之外的数据列分区。
由于RANGE分区是最常用的分区方案,其他三种分区方案用的相对很少。这里主要介绍RANGE方案。
在实际操作分区前我们得了解下分区的几点限制:
- 数据表分区上限最多只能有1024个分区。
- 同一个表的所有分区必须使用相同存储引擎。
- 数据库使用分区则不能使用外键约束,会报错。
RANGE分区实操
按照RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行。
CREATE TABLE order_info (
id int not NULL PRIMARY KEY auto_increment,
goods_title VARCHAR(50) NOT NULL,
created_at date
)
PARTITION BY RANGE (id) (
PARTITION order1 VALUES less than (10),
PARTITION order2 VALUES less than (20),
PARTITION order3 VALUES less than (30),
PARTITION order4 VALUES less than (40),
PARTITION order5 VALUES less than (50)
);
创建一张order_info表并创建了5个分区,接下来我们查看order_info表分区情况,看是否成功形成5个分区:
SELECT partition_name part,
partition_expression expr,
partition_description descr
,table_rows FROM information_schema.`PARTITIONS`
WHERE table_schema=SCHEMA() AND table_name='order_info';
可以看到上面的创建分区我们使用values less than语句,我们将id<10的数据保存在order1分区,将id范围在10-20保存在order2分区,以此类推创建了五个分区。
现在我们可以写个存储过程插入50条数据测试下:
CREATE PROCEDURE test010()
BEGIN
DECLARE i INT;
SET i=1;
START TRANSACTION;
WHILE i<=50 DO
INSERT INTO order_info VALUES(NULL,'测试数据',NOW());
SET i=i+1;
END WHILE;
COMMIT;
END
//
delimiter;
CALL test010();
可以明显看到报错了,报没有分区可以存放id为50的值的错误信息。因为我们设置的第五个分区范围为40-50,右边不包含,所以超过50直接报错无法存放。这很不合理,所以说我们得对分区做一下调整
我们使用alter table命令新增分区order6保存大于50的值:
ALTER TABLE order_info ADD PARTITION(PARTITION order6 VALUES less than (MAXVALUE));
我们增加了order6分区,值设置为maxvalue,表示如果值大于order5设置的上限则保存进入order6分区。
我们插入500条数据到数据库中测试下效果:
我们查看下分区下各自含有几条数据
我们可以看到完全按照我们设置的分区进行数据存放到不同的分区。可能有人会说我怎么确认order1分区存放的9条数据一定是id为1-10的呢?
这个其实测试很简单,我们直接删除order1分区,然后查看数据库数据:
ALTER TABLE order_info DROP PARTITION order1;
可以看到我们删除掉order1分区之后,id10以下的数据也跟着被删除了,所以可以表示id在10以下的确实保存在分区order1中。而我们完全可以按照时间来进行分区,然后将半年以上的数据移到备用表然后删除分区,这样就可以提高我们单表的性能。在删除数据时直接删除分区会远远比delete数据效率高很多。
SQL如何查询分区数据
在进行select/update/delete时如果where后面的限制条件包含分区字段id时会自动去对应分区中查找,否则还是全表扫描。
EXPLAIN SELECT * FROM order_info WHERE id = 20;
可以看到上图只查询了 order3 分区。
EXPLAIN SELECT * FROM order_info WHERE goods_title = '测试数据2';
可以看到上图查询了 order2,order3,order4,order5,order6分区,共查询了491行 。
range分区字段只支持整型,如果需要对时间日期这样的字段进行range分区,可以通过相关函数将类型转为整型再分区。