这一段时间对数据库优化方面的认识深有体会,就以MySQL为例测试一下分区表的性能
MySQL5.0好像不支持分区,我用的5.5版本,测试是否支持可通过以下方法:
SHOW VARIABLES LIKE '%partition%';
如果结果为yes则说明支持,如下图:
CREATE TABLE no_part_tab
(id INT DEFAULT NULL,
remark VARCHAR(50) DEFAULT NULL,
d_date DATE DEFAULT NULL
)ENGINE=MYISAM
CREATE TABLE part_tab
(id INT DEFAULT NULL,
remark VARCHAR(50) DEFAULT NULL,
d_date DATE DEFAULT NULL
)ENGINE=MYISAM
PARTITION BY RANGE(YEAR(d_date))(
PARTITION p0 VALUES LESS THAN(1995),
PARTITION p1 VALUES LESS THAN(1996),
PARTITION p2 VALUES LESS THAN(1997),
PARTITION p3 VALUES LESS THAN(1998),
PARTITION p4 VALUES LESS THAN(1999),
PARTITION p5 VALUES LESS THAN(2000),
PARTITION p6 VALUES LESS THAN(2001),
PARTITION p7 VALUES LESS THAN(2002),
PARTITION p8 VALUES LESS THAN(2003),
PARTITION p9 VALUES LESS THAN(2004),
PARTITION p10 VALUES LESS THAN maxvalue);
MySQL没有像oracle那样的序列,所以要用循环插入,每张表插入800w数据做测试
DROP PROCEDURE IF EXISTS no_load_part;
DELIMITER//
CREATE PROCEDURE no_load_part()
BEGIN
DECLARE i INT;
SET i =1;
WHILE i<8000001
DO
INSERT INTO no_part_tab VALUES(i,'no',ADDDATE('1995-01-01',(RAND(i)*36520) MOD 3652));
SET i=i+1;
END WHILE;
END//
DELIMITER ;
CALL no_load_part;
DROP PROCEDURE IF EXISTS load_part;
DELIMITER&&
CREATE PROCEDURE load_part()
BEGIN
DECLARE i INT;
SET i=1;
WHILE i<8000001
DO
INSERT INTO part_tab VALUES(i,'partition',ADDDATE('1995-01-01',(RAND(i)*36520) MOD 3652));
SET i=i+1;
END WHILE;
END&&
DELIMITER ;
CALL load_part;
说明:首先删除procedure,如果已存在的话,然后开始创建新的,delimiter是指定分隔符,默认的是“;”,这里我们不能用分号,就指定为“//”或者“&&”,创建时定义个int类型i,然后通过do…while循环,等程序执行完毕后把分隔符重新指定为“;”,然后通过call语句写入数据库
SELECT COUNT(*) FROM no_part_tab WHERE d_date > DATE '1995-01-01' AND d_date< DATE '1995-12-31';
SELECT COUNT(*) FROM part_tab WHERE d_date > DATE '1995-01-01' AND d_date< DATE '1995-12-31';
第一次查询的结果对比。不分区是10.90秒,分区是0.28秒,可以看出分区效率提高了约97%,第一次查询速度慢,当多查询几次效率一般会提高,我也试了试,下面是结果:
如图可以看出,多查询几次后,不分区的表稳定在2.17秒左右,分区表一直在0.28秒左右,分区的效率依然相比提高约87%,分区效果相当显著
测试数据库相对简单,当数据复杂并且外键多时时,MySQL处理近千万的数据的表时效率是不太好的,这是分区就会显得特别的重要
测试过程中需要了解的注意点: