1.分库
在我们的常见中,正常的都是说在一个库里面有多个表,例如,在某个学校数据库中,有学生表,成绩表,学分表等等,这个数据存储方式就是单库多表。
当数据量变的很多的时候,例如银行系统,或者淘宝这种的,交易量每天都会很多,有的时候甚至会暴增,例如双十一,这个时候如果是一个库的话压力就可能变得很大,一个库就会影响我们的效率,这里就会使用到分库来缓解服务器的压力,实现负载均衡。
分库,主要是为了海量数据的存储问题。可以按照功能或者业务将不同的表放在不同的库中,例如学生表可以单独放在一个学生库中,成绩表可以单独放在成绩库中,这样的话每一个库所承受的压力就会降低很多。
如何实现分库,和分表的优点类似,例如字段的id是7,分为3个库,那个这个数据就会在7%3=1,第一个库里面,这样一来将海量数据拆分开来,会提高系统的运行效率。
2.分表
分表的原因:
01:当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,甚至系统可能会卡死。分表的目的就在于此,减小数据库的负担,缩短查询时间。
02:mysql中有一种机制是表锁定和行锁定,是为了保证数据的完整性。表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行。行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操作。
垂直切分:采用垂直切分的主要目的是因为表多而导致数据量多,这个时候我们就需要垂直切分,可以按照业务功能来切分,也可以按照其他规则。这种切分主要是按照字段的形式,最简单的就是主键+常用列和主键+不常用列来区分,因为对某个表的列减少了这样的话表的操作效率就会提升,也就是通常说的大表变小表。
优点:可以使得行数据变小,一个数据块 (Block) 就能存放更多的数据,在查询时就会减少 I/O 次数
便于数据维护
缺点:引起表连接操作,复杂度提高了
主键冗余
水平切分:采用水平切分主要是由于单张表的数量太多导致数据量大,这个时候采用水平切分。这种切分的主要是将数据将大表切分成小表,例如微博功能,将经常访问的,点击量高的数据切分出来,这样的话就能大大的提高小效率。常见的切分方式有按时间,按字段,按范围等。
优点:单库单表的数据保持在一定的量级,这样的话会有助于性能的提高
提高了系统的稳定性和负载能力,让系统能更好的运行
缺点:数据由于分散,难以维护
3.分区
将大表进行分区,不同分区可以放置在不同存储设备上,这些分区在逻辑上组成一个大表,对客户端透明。分区的方式和分表类似,关键字是partition。
创建分区:RANEE分区
CREATE TABLE employees (
id INT NOT NULL, fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL, store_id INT NOT NULL)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE);
注意:
1. RANGE分区的返回值必须为整数。
2. PARTITION p3 VALUES LESS THAN MAXVALUE 是非必需的。
当store_id小鱼6的时候,这些数据就会被放在p0分区,当小于11的时候,挡在p1分区,依此类推。
特殊分区:RANGE COLUMNS
它与RANGE分区的区别:
1. RANGE COLUMNS不接受表达式,只能是列名。而RANGE分区则要求分区的对象是整数。
2. RANGE COLUMNS允许多个列,在底层实现上,它比较的是多个列值组成的列表,而RANGE比较的是标量,即数值的大小。
3. RANGE COLUMNS不限于整数对象,date,datetime,string都可作为分区列。
CREATE TABLE rcx ( a INT, b INT, c CHAR(3), d INT)
PARTITION BY RANGE COLUMNS(a,d,c)
( PARTITION p0 VALUES LESS THAN (5,10,'cc'),
PARTITION p1 VALUES LESS THAN (10,20,'dd'),
PARTITION p2 VALUES LESS THAN (15,30,'ee'),
PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE));
LIST分区,与RANGE分区差不多类似,只是RANGE分区后面是一个值,而LIST分区后面是一共list组成的,例如PARTITION p0 VALUES IN (1,2,3,4,5)这种情况。
LIST COLUNMS,是LIST分区的一个特殊情况,多个列支持string,date和datetime类型,也就是将后面的列变成时间的形式。
HASH分区,HASH分区也类似于RANGE分区,PARTITION BY HASH(store_id),里面的strod_id必须是整数值,可以不用指定字句,写PARTITIONS 4,这样就会默认分区数为4.它的底层实现是基于MOD函数的,例如你要添加一个数值为9的数据,那么就会实现MOD(9,4),这样就会放在1这个分区里面。
KEY分区,和HASH类似,HASH分区里面只能是一个列,而KEY分区里面可以是多个列,HSAH分区里面可以是列的表达式,而KEY分区不能为列的表达式。KEY分区在有主键或者唯一简答情况下,可以不用指定,会默认的为主键或者唯一键,如果没有的情况下,必须显示的指定出来。在底层的算法上,HSAH分区取的是MOD表达式的返回值,而KEY分区是取列的MD5值。
PARTITION BY KEY(s1)
PARTITIONS 10;
LINEAR HASH分区,是HASH分区的一种特殊情况
CREATE TABLE employees
( id INT NOT NULL, fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT, store_id INT)
PARTITION BY LINEAR HASH( YEAR(hired) )
PARTITIONS 4;
这是一种线性哈希分区,对于给出的表达式expr,这条记录被存储在使用线性散列分区的分区号N从num中获取,其中,N的获得算法是
Step 1. 找到一个大于等于num的2的幂,这个值为V,V可以通过下面公式得到:
V = Power(2,Ceiling(Log(2,num)))
例如:刚才设置了4个分区,num=4,Log(2,4)=2,Ceiling(2)=2,power(2,2)=4,即V=4
Step 2. 设置N=F(column_list)&(V-1)
例如:刚才V=4,store_id=234对应的N值,N = 234&(4-1) =2
Step 3. 当N>=num,设置V=Ceiling(V/2),N=N&(V-1)
例如:store_id=234,N=2<4,所以N就取值2,即可。
假设上面算出来的N=5,那么V=Ceiling(2.5)=3,N=234&(3-1)=1,即在第一个分区。
线性哈希分区的优点是分区的添加,删除,合并和拆分要快得多,这在处理包含极大量(兆兆字节)数据的表时非常有用。缺点是与使用常规散列分区获得的分布相比,数据不太可能在分区之间均匀分布。
LINEAR KEY类似于LINEAR HSAH,只是算法不同。
4.读写分离,主从复制
对于绝大多数情况来说,读的情况要远远大于写的情况,所以一般都是一个主库,一个从库,也可以是两个从库,从库是由主库复制过来的,也就是主-从-从部署模型。所以,一般写的操作都是在主库里面进行的,然后再异步同步到从库,这个时候如果主库崩溃了,那么从库也就崩溃。在主库同步到从库中间,如果系统当时处于过度繁忙状态,会导致同步的延迟会明显,如果从库的使用次数过于频繁,也就导致延迟的问题明显。所以,主库就会显得更加重要,是整个集群的瓶颈。还有一个是主-主-从部署模式,两个主库和一个从库,对于稳定性提高了很多,不过在性能上会降低很多。对于具体使用哪种部署模式,如果读的压力过大,就采用主-从-从,写的压力过大,就采用主-主-从。