在大容量,高负荷的web系统中,对数据库进行一系列拆分,可有效提高数据库容量和性能。在初学程序的早期,程序员一般都喜欢按传统数据库设计模式,设计为单库和单一功能表的结构,这样的结构在数据量和并发量达到必定程度以后,会出现严重性能问题和维护问题。在出现问题的时候才着手进行优化,会很是痛苦,因此应该在系统架设之初就考虑好以后会出现的问题。
目前有些数据库策略是采用单库结构,而后经过同步分发到数台服务器实现读写分离。我的以为这样的策略很是笨拙,仍是想办法将其分隔开来好,不然每台机器的内存都很容易超支。
通常只对数据量比较大的表进行拆分,这应该没有什么异议;还有一种是有可能会进行维护的比较重要的表,好比文章目录表,若是有从其它系统倒数据进来的可能的话,也要拆掉,否则倒数据时一不当心把目录表弄坏了,发现忘了备份,那真是欲哭无泪。
下面来分析一下:
1、时间结构
若是业务系统对时效性较高,好比新闻发布系统的文章表,能够把数据库设计成时间结构,按时间分有几种结构:
1) 平板式
表相似:
article_200901
article_200902
article_200903
用年来分仍是用月可自定,但用日期的话表就太多了,也没这必要。通常建议是按月分就能够。
这种分法,其难处在于,假设我要列20条数据,结果这三张表里都有2条,那么业务上颇有可能要求读三次表。若是时间长了,有几十张表,而每张表是0条,那不就是要读完整个系统的表才行么?另外这个结构,要做分页是比较难实现的。
主键:在这个系统中,主键是13位带毫秒的时间戳,不要用自动编号,不然难以经过主键定位到表,也能够在查询时带上时间,但比较烦琐。
2) 归档式
表相似:
article_old
article_new
为了解决平板式的缺点,能够采用时间归档式设计,能够看到这个系统只有两张表。一张是旧文章表,一张是新文章表,新文章表放2个月的信息,天天按期把2个月中的最先一天的文章纳入旧表中。这样一方面能够解决性能问题,由于通常新闻发布系统读取的都是新的内容,旧的内容读取少;第二能够委婉地解决功能问题,好比平板式所说的问题,在归档式中最多也只须要读2张表就完成了。
归档式的缺点在于旧表容量仍是相对比较大,若是业务容许,可对旧表中的超旧内容进行再归档或直接清理掉。
2、版块结构
若是按照文章的所属版块进行拆表,好比新闻、体育版块拆表,一方面可使每一个表数据量分离,另外一方面是各版块之间相互影响可降到最低。假如新闻版块的数据表损坏或须要维护,并不会影响到体育版块的正常工做,从而下降了风险。版块结构同时经常使用于bbs这样的系统。
板块结构也有几种分法:
1) 对应式
对于版块数量很少,并且较为固定的形式,就直接对应就好。好比新闻版块,能够分出新闻的目录表,新闻的文章表等。
news_category
news_article
sports_category
sports_article
可看到每个版块都对应着一组相同的表结构,好处就是一目了然。在功能上,由于版块之间仍是有一些隔阂,因此须要联合查询的需求很少,开发上比时间结构的方式要轻松。
主键:依旧要考虑的,在这个系统中,主键是版块+时间戳,单纯的时间戳或自动编号也能用,查询时要记得带上版块用于定位表。
2) 冷热式
对应式的缺点是,若是版块数量很大并且不肯定,那要分出的表数量就太多了。举个例子:百度贴吧,若是按一个词条一个表设计,那得有多少张表呢?
用这样的方式吧。
tieba_汽车
tieba_飞机
tieba_火箭
tieba__unite
这个表汽车、火箭表是属于热门表,定义为新建的版块放在unite表里面,待到其超过一万张主贴的时候才开对应表结构。由于在贴吧这种系统中,冷门版块确定比热门版块多得多,这些冷门版块一般只有几张帖子,为它们开表也太浪费了;同时热门版块数量和访问量等,又比冷门版块多得多,很是有特色。
unite表还能够扩展成哈希表,利用词条的md5编码,能够分红n张表,我算了一下,md5前一位可分16张表,两位便是256张表。
tieba_unite_ab
tieba_unite_ac
...
3、哈希结构
哈希结构一般用于博客之类的基于用户的场合,在博客这样的系统里有几个特色,1是用户数量很是多,2是每一个用户发的文章数量都较少,3是用户发文章不按期,4是每一个用户发得很少,但总量仍很是之大。基于这些特色,用以上所说的任何一种分表方式都不合适,一没有固定的时效不宜用时间拆,二用户不少,并且还恰恰都是冷门,因此也不宜用版块(用户)拆。
哈希结构在上面有所说起,既然按每一个用户很差直接拆,那就把一群用户归进一个表好了。
blog_aa
blog_ab
blog_ac
...
如上所说,md5取前两位哈希能够达到1296张表,若是以为不够,那就再加一位,总数可达46656张表,还不够?
表的数量太多,要建立这些表也是挺麻烦的,能够考虑在程序里往数据库insert以前,多执行一句判断表存在与否并建立表的语句,很实用,消耗也并不很大。
主键:依旧要考虑的,在这个系统中,主键是用户ID+时间戳,单纯的时间戳或自动编号也能用,但查询时要记得带上用户名用于定位表。
4、总分结构
以上的这些结构,根据每一个业务系统,能想出的估计还有不少。不过如今互联网业务愈来愈复杂了,有些时候,单一的拆分法还不能实现需求,须要几种拆分方案一块儿实施,多管齐下,这时候其中的逻辑会让人绕晕。我就开发过一个系统,仅仅是将哈希结构和时间结构混着一用,以为逻辑就至关复杂。
因此,除了拆表以外,按最原始的单库单表,再建一个总表,是很是有利的架构。在这个架构中,每次往数据库会写入两倍数据,读取主要依赖拆表提高性能,总表用于实现拆表后难以实现的功能而且用于天天的定时备份;另外总表和分表还相互是一个完整的备份,任何一个分表损坏或数据不正常,均可以从总表中读到正确的数据并恢复,反之亦然。
在总分结构中,让人感到质疑的是总表的性能和可维护性。个人方案是总表可采用相对能保证稳定的一些服务软件和架构,例如oracle,或 lvs+pgpool+PostgreSQL,重点保证数据稳定;相对的,分表就用轻量级的mysql,重点在于速度。可以对总分表各采用不一样的软件和方案,也是总分结构的一大特色。
总结:如何经过拆表来优化系统,最基本的是要按业务需求和特色分析。本文仅仅是提供了几种基本方法,具体工做要先动脑好好想,千万不可乱套,用错了工做量要加十倍噢。mysql