sql解决数据量过大问题的方法
通常情况下,我们用sql数据库存储我们的数据。在项目刚开始的时候,用户量比较小,相应的数据量也比较小,并发压力也比较小。当我们的web应用越来越受欢迎后,用户量会激增,访问量会激增,数据量也会变大 。于是会经历这样的几个变化。
1.主备分离
用户量激增的时候,常常最先开始发生的问题是,读写性能不够。于是为了解决这个问题,创建几个备库。所有的写操作都在主库上执行,然后同步到备库上,所有的读操作都在备库。
这样重构后读写性能会比较好。
2.分库
但随着用户量进一步增加,这个时候同一个应用的所有的表的数据已经无法同时容纳在一台机器上了。这个时候又需要重构。
解决办法是将某些数据量特别大的表抽出来,单独存放在一台机器上。这在一定程序上可以缓解数据量过大的问题。
3.分表
当数据量进一步增加的时候,会发现就算一个机器只存储一张也存储不下了。
这时候的做法是将一张表的内容切分成多个表分别存储到不同的机器。
经过上面三个步骤数据过大的问题基本解决了。
but,关键的but
分库分表后,我们失去了什么
先看看sql数据库的一些关键特性
a事务:包括A(原子性),C(一致性),I(隔离性),D(持久性)
b多表联合:join,select from多个表的时候都是这种情况
c索引:根据某个条件来查询
e聚合操作:count(),sum(), group by , having
1.主备分离时
此时失去了事务的隔离性。
如果在一个事务中即有读也有写,那么读操作是在备库上执行,而写操作是在主库上执行,而sql的事务管理器无法管理不同机器上的操作。主机器的值发改变时,备库是无法瞬间感知到的,同步需要时间,虽然这个时间很短,可能只有1/1000秒,但就算是这1/1000的差别也会导致事务失效。
2.分库时
- 此时失去了事务。事务中只要涉及到多张分布在不同机器上的表的操作,那么整个事务就不会生效。sql数据库本身无法管理跨机器的事务。当然也有跨机器的事务方案,但一般来说,效率都非常低下,因此分布式事务这种方案几乎可以忽略。
- 多表联合完全失效。当表处于不同的机器上时,表之间的联合查询那将是完全不可能。
3.分表时
此时sql的关键特性几乎都不能用。
事务,多表联合,索引,聚合几乎都不可用。
索引不可用。比如一个博客表,一般会按用户来分表,将同一个用户的所有的数据都放在同一台机器,但这时如果我们创建时间来查询,想查询所有的用户在今天发表的日志,那么此时就会失效。这时需要到每一个分表上进行查询然后将查询结果进行拼装。而原生的sql是完成不了的。
当索引不可用时,聚合操作当然也是不准的。
sql or nosql
因此可以看到当数据量变大时sql几乎就失效了。几乎所有关键特性都不可用了。能用就差不多(当然还有些许其它的)只有通过主键或分区列(决定数据在哪台机器的列,例如时间,用户ID)进行操作,通过其它维度的操作将非常困难。
来看看nosql数据库,比如hbase cassandra mongodb,好像差不多也是只能通过主键进行操作。
因此可以说,当关系型数据库进行了分库分表后,系统就变成了nosql,因为关系统型数据库的大部分的重要特性已经完全不可用了,可用的部分nosql也几乎都有。
虽然分库分表解决了大数据量的问题,但nosql确走得更远了,提供更多令人激动的特性。
1.自动化扩容。对于关系型数据库来说,分库分表的扩容是一个非常非常非常困难的事情,每一次扩容必须要提前做好规划,必须认真评估,搞不好还需要数据迁移,对于一个正在运行着的系统来说这是非常巨大的挑战。而nosql数据,已经将这些功能内置,自动化。
2.同步副本。hbase cassandra都实现了同步副本功能,每个表都可以根设定值来同步到其它机器上,当一台机器宕机,操作直接转移到另外的机器,这种转移是瞬间完成。当然mysql oracle也有主备切换的功能,但主备的切换需要时间。因此nosql对断网宕机有更好的容错性。
当然现在已经有很多的公司转向了nosql,但采用关系型数据库分库分表的依然非常多。但在大数据量下,从sql转向nosql已经成了一个势不可挡的趋势。