数据的垂直切分
kevin.Zhu 发布于:2013-1-16 16:46 分类:大数据存储 有 10 人浏览,获得评论 0 条
据的垂直切分到底是如何切分的。数据的垂直切分,也可以称为纵向切分。将数据库想象成由很多个一大块一大块的"数据块"(表)组成,垂直地将这些"数据块"切开,然后把它们分散到多台数据库主机上面。这样的切分方法就是垂直(纵向)的数据切分。
一个架构设计较好的应用系统,其总体功能肯定是由很多个功能模块所组成的,而每一个功能模块所需要的数据对应到数据库中就是一个或多个表。而在架构设计中,各个功能模块相互之间的交互点越统一、越少,系统的耦合度就越低,系统各个模块的维护性及扩展性也就越好。这样的系统,实现数据的垂直切分也就越容易。
功能模块越清晰,耦合度越低,数据垂直切分的规则定义也就越容易。完全可以根据功能模块来进行数据的切分,不同功能模块的数据存放于不同的数据库主机中,可以很容易就避免跨数据库的 Join 存在,同时系统架构也非常清晰。
当然,很难有系统能够做到所有功能模块使用的表完全独立,根本不须要访问对方的表,或者须要将两个模块的表进行 Join 操作。这种情况下,就必须根据实际的应用场景进行评估权衡。决定是迁就应用程序将需要 Join 的表的相关模块都存放在同一个数据库中,还是让应用程序做更多的事情--完全通过模块接口取得不同数据库中的数据,然后在程序中完成 Join 操作。
一般来说,如果是一个负载相对不大,而且表关联又非常频繁的系统,那可能数据库让步,将几个相关模块合并在一起,减少应用程序工作的方案可以减少较多的工作量,是一个可行的方案。
当然,通过数据库的让步,让多个模块集中共用数据源,实际上也是间接默许了各模块架构耦合度增大的发展,可能会恶化以后的架构。尤其是当发展到一定阶段,发现数据库实在无法承担这些表所带来的压力,不得不面临再次切分时,所带来的架构改造成本可能远远大于最初就使用切分的架构设计。
所以,在数据库进行垂直切分的时候,如何切分、切分到什么样的程度,是一个比较考验人的难题。这只能在实际的应用场景中通过平衡各方面的成本和收益,才能分析出一个真正适合自己的拆分方案。
比如在本书所使用的示例系统的 example 数据库中,我们简单分析一下,然后设计一个简单的切分规则,进行一次垂直拆分。
系统功能基本可以分为4个功能模块:用户、群组消息、相册以及事件,分别对应为如下这些表:
(1)用户模块表:user,user_profile,user_group,user_photo_album
(2)群组讨论表:groups,group_message,group_message_content,top_message
(3)相册相关表:photo,photo_album,photo_album_relation,photo_comment
(4)事件信息表:event
初略一看,没有哪个模块可以脱离其他模块独立存在,模块与模块之间都存在着关系,莫非无法切分?
当然不是,再稍微深入分析一下,可以发现,虽然各个模块所使用的表之间都有关联,但是关联关系还算清晰,也比较简单。
群组讨论模块和用户模块之间主要存在通过用户或群组关系来进行关联。一般都会通过用户的 id 或 nick_name 及 group 的 id 来进行关联,通过模块之间的接口实现不会带来太多麻烦。
相册模块仅仅与用户模块存在用户的关联。这两个模块之间的关联基本只有通过用户 id 关联的内容,简单清晰,接口明确。
事件模块与各个模块可能都有关联,但是都只关注其各个模块中对象的ID信息,同样比较容易分拆。
所以,第一步可以将数据库按照功能模块相关的表进行一次垂直拆分,每个模块所涉及的表单独分到一个数据库中,模块与模块之间的表关联在应用系统端都通过接口来处理。如数据垂直切分示意图(图14-1)所示
通过这样的垂直切分之后,之前只能通过一个数据库来提供的服务,就被分拆成4个数据库来提供服务,服务能力自然是增加几倍了。
垂直切分的优点:
数据库的拆分简单明了,拆分规则明确;
应用程序模块清晰明确,整合容易;
数据维护方便易行,容易定位。
垂直切分的缺点:
部分表关联无法在数据库级别完成,要在程序中完成;
对于访问极其频繁且数据量超大的表仍然存在性能瓶颈,不一定能满足要求;
事务处理相对复杂;
切分达到一定程度之后,扩展性会受到限制;
过度切分可能会带来系统过于复杂而难以维护。
针对于垂直切分可能遇到数据切分及事务问题,在数据库层面实在是很难找到一个较好的处理方案。实际应用案例中,数据库的垂直切分大多是与应用系统的模块相对应的,同一个模块的数据源存放于同一个数据库中,可以解决模块内部的数据关联问题。而模块与模块之间,则通过应用程序以服务接口的方式来相互提供所需要的数据。虽然这样做在数据库的总体操作次数方面确实会有所增加,但是在系统整体扩展性及架构模块化方面,都是有益的。可能某些操作的单次响应的时间会稍有增加,但是系统的整体性能很可能反而会有一定的提升。而扩展瓶颈问题,就只能依靠下一节将要介绍的数据水平切分架构来解决了。