分表和分区解决的是单表数据量大时的SQL性能压力,另外分表也能一定程度上提高并发;


1. 什么是分表、分区?

分表和分区是不同层次的概念

  1. 分表:
    分表是开发人员的物理设计,目的是:在单表有大数据量的情况下保证SQL执行性能,也能提高并发
  • 我们可以将一个大表(指存储了百万级乃至千万级条记录的表)按照一定的规则分解成多张具有独立存储空间的子表。
  • 程序读写表数据时可以根据建表时定好的规则而知道应该操作的表名,继而去操作相应的字表。
  1. 分区:
    分区是MySQL的一种技术设计,目的是:提高I/O。
  • MySQL将一个表的数据分段在多个位置存放,表还是那一张表,但是DB会依据自定义的条件去组织分区的数据。
  • 查询时DB会依据分区的结果自动去相应的分区中查询。

2. 为什么要分表、分区?

程序员的分表设计,以及MySQL的分区技术虽然实现方式不同,但目的是相同的,可以描述如下:

我们在日常开发中不可避免的会遇到大数据量表的情况,这样的表过于庞大,导致进行数据库查询和更新时耗时太长,性能下降,如果有联合查询那么性能会更糟糕。所以,分区和分表的目的就是减少数据库的执行负担,稳定SQL性能。


3. 分表、分区的关系与选择

  1. 首先在设计上来说:
  • 分表是按照程序员的意愿,在物理上拆分表(分表可以在一定程度上提高并发);
  • 分区是将一张表在逻辑上进行水平分割。
  1. 应用场景上来说:
  • 对于访问量不大,但是表数据很多的表,可以采用分区
    毕竟MySQL提出分区主要就是想提高磁盘I/O。但是从实际企业应用来看,MySQL的表分区、Cluster技术都还没有被企业普遍接受。
  • 对于访问量大且数据多的表,可以采取分表和分区结合的方式

4. 分表

  1. 垂直分割(并不常用)
    就是将一个表按照字段来分,每张表保证有相同的主键就好。一般来说,将常用字段和大字段分表来放。
  • 优势:比没有分表来说,提高了查询速度,降低了查询结果所用内存;
  • 劣势:没有解决大量记录的问题,对于单表来说随着记录增多,性能还是下降很快;
  1. 水平分割(重要)
    水平分割是企业最常用到的,水平拆分就是大表按照记录分为很多子表:

水平分的规则完全是自定义的,有以下几种参考设计:

  1. hash、自增id取模
    对某个字段进行hash来确定创建几张表,并根据hash结果存入不同的表;
  2. 按时间
    根据业务可以按照天、月、年来进行拆分;
  3. 按每个表的固定记录数
    一般按照自增ID进行拆表,一张表的数据行到了指定的数量,就自动保存到下一张表中。比如规定一张表只能存1-1000个记录;
  4. 将老数据迁移到一张历史表
    比如日志表,一般只查询3个月之内的数据,对于超过3个月的记录将之迁移到历史子表中;

分表时需要的设计

  1. 查询时:要根据预定义规则查询不同的子表;
  2. select/update/delete时:极有可能涉及多张表,必须在程序逻辑上的事务中都包括好所有的表。

5. 分区

分区其实最好查看MySQL的官方文档,毕竟它做的这个技术现在还在不断发展。

  1. 水平分区
    有几种模式如下:
  1. Range:定义范围来分
  2. Hash:定义Hash来分
  3. Key:Hash的一种延伸
  4. List(预定义列表):自己定义几个值来分
  5. Composite(复合模式):对1234组合使用
  1. 垂直分区
    一般将大text和BLOB列分到另一个区
  2. 语法
CREATE TABLE part_table 
( 
c1 int default NULL, 
c2 varchar(30) default NULL, 
c3 date default NULL
) engine=myisam 
PARTITION BY RANGE (year(c3)) 
(
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 (2010),
PARTITION p11 VALUES LESS THAN MAXVALUE 
);

对比正常语法

create table no_part_table 
(
c1 int(11) default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=myisam;

以上。