有人说分区表是鸡腿,不对是鸡排,也不对,应该是鸡胸。
到5.7后分区表功能也丰富了,还支持双层分区。虽然比O还差一截!
CREATE TABLE table_name (
id INT AUTO_INCREMENT,
fieldX VARCHAR(100) NOT NULL,
order_day DATETIME NOT NULL,
PRIMARY KEY(id, order_day)
) ENGINE=Innodb
PARTITION BY RANGE(YEAR(order_day)) (
PARTITION p_2015 VALUES LESS THAN (2015),
PARTITION p_2016 VALUES LESS THAN (2016),
PARTITION p_2017 VALUES LESS THAN (2017),
PARTITION p_catchall VALUES LESS THAN MAXVALUE);
瞧跟ORACLE风格差不多,好有亲切感!
另外还有 LIST 分区 HASH 分区 KEY 分区。
ALTER TABLE table_name ANALYZE PARTITION p_2017;
ALTER TABLE table_name rebuild PARTITION p_2017;
连管理操作都一摸一样!
不建议mysql分区表
1)分区表,分区键设计不太灵活,如果不走分区键,很容易出现全表锁
2)一旦数据量并发量上来,如果在分区表实施关联,就是一个灾难
3)自己分库分表,自己掌控业务场景与访问模式,可控。分区表,研发写了一个sql,都不确定mysql是怎么玩的,不太可控
感觉上面3条理由都很牵强附会!
分区键设计不太灵活? 分表字段就灵活了吗? 同样一张表就那么多字段!
另外MYSQL SERVER 层 短暂路由时候会锁全部分区,这MYCAT中间件这层性能路由消耗也一样啊。
按AGE范围分区表CREATE TABLE tbl_user_part_range
(
id
int(11) NOT NULL,
username
varchar(255) DEFAULT NULL,
email
varchar(20) DEFAULT NULL,
age
tinyint(4) NOT NULL,
type
int(11) DEFAULT NULL,
create_time
datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id
,age
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (age)
(PARTITION p0 VALUES LESS THAN (20) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (40) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (60) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (80) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
把单表500万数据插入
INSERT INTO tbl_user_part_range SELECT * FROM tbl_user_no_part; --195.264
等值查询5万笔
select * from tbl_user_no_part where age =80 --8.783 4,9928
1 SIMPLE tbl_user_part_range ALL 1046646 Using where
比单表无索引下62秒快乐不少!
大于等于查询百万条记录
select * from tbl_user_part_range where age >=80 --8.783 105,0969
1 SIMPLE tbl_user_part_range ALL 1046646 Using where
select * from tbl_user_no_part where age <=20 --20.943秒 100,0013条
1 SIMPLE tbl_user_part_range ALL 1941117 Using where
而单表无索引下需要78秒 同一台机器哦!
select * from tbl_user_no_part where age <=20 --78.076秒 100,0013条
统计数量通过主键索引也快乐不少
select count(*) from tbl_user_part_range --41.893s
1 SIMPLE tbl_user_part_range index PRIMARY 5 4980156 Using index
等值无索引 比单表有索引差很多
select * from tbl_user_part_range where username ='lJMJiOtD'; --41.049 2行
1 SIMPLE tbl_user_part_range ALL 4980156 Using where
创建二级索引NAME
select * from tbl_user_part_range where username ='lJMJiOtD'; --0.907 2
1 SIMPLE tbl_user_part_range ref ix_user_part_range ix_user_part_range 768 const 4 Using where
分区二级索引比单表二级索引性能上下降12.5%
同样走错索引也比单表走错索引快乐2千秒
select * from tbl_user_part_range where username like 'a%';--1861.322 19,1388
1 SIMPLE tbl_user_part_range range ix_user_part_range ix_user_part_range 768 387627 Using where
目前来说分区表是不错的性能提高选项,要注意的是二级索引不参与分区,这跟ORACLE分区表的全局索引一样。
这样二级索引+分区键的SQL 还是走子分区全表扫描。 如果走索引比然会跨子分区操作。这就有选择,如果通过二级索引返回单笔数据,经过分区反而变慢是很用可能的; 反正通过二级索引返回大量数据,经过分区有可能提升很快,主要是可能通过二级索引返回的主键基本散落在少数分区中。
分区应该说适合业务并发量不大,用户响应时间要求不会很苛刻的业务场景。其实ORACLE 11G 12C 的分区表也无法胜能电商互联网之类的应用场景。到了19C 利用分区表分实例路由功能去支持。
瞧 分表分库实际上就是把分区表移到另外台物理机上跑而已。通过硬件来支持业务压力。