水平拆分的意思,就是把一个表的数据给弄到多个库的多个表里去,但是每个库的表结构都一 样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全部数据。水平拆分的意 义,就是将数据均匀放更多的库里,然后用多个库来扛更高的并发,还有就是用多个库的存储 容量来进行扩容。
垂直拆分的意思,就是把一个有很多字段的表给拆分成多个表,或者是多个库上去。每个 库表的结构都不一样,每个库表都包含部分字段。一般来说,会将较少的访问频率很高的字 段放到一个表里去,然后将较多的访问频率很低的字段放到另外一个表里去。因为数据库 是有缓存的,你访问频率高的行字段越少,就可以在缓存里缓存更多的行,性能就越好。这个 一般在表层面做的较多一些。
这个其实挺常见的,不一定我说,大家很多同学可能自己都做过,把一个大表拆开,订单表、 订单支付表、订单商品表。
还有表层面的拆分,就是分表,将一个表变成 N 个表,就是让每个表的数据量控制在一定范 围内,保证 SQL 的性能。否则单表数据量越大,SQL 性能就越差。一般是 200 万行左右,不要 太多,但是也得看具体你怎么操作,也可能是 500 万,或者是 100 万。你的SQL越复杂,就最 好让单表行数越少。
好了,无论分库还是分表,上面说的那些数据库中间件都是可以支持的。就是基本上那些中间 件可以做到你分库分表之后,中间件可以根据你指定的某个字段值,比如说 userid,自动路 由到对应的库上去,然后再自动路由到对应的表里去。
你就得考虑一下,你的项目里该如何分库分表?一般来说,垂直拆分,你可以在表层面来做, 对一些字段特别多的表做一下拆分;水平拆分,你可以说是并发承载不了,或者是数据量太 大,容量承载不了,你给拆了,按什么字段来拆,你自己想好;分表,你考虑一下,你如果哪 怕是拆到每个库里去,并发和容量都 ok 了,但是每个库的表还是太大了,那么你就分表,将 这个表分开,保证每个表的数据量并不是很大。
有两种分库分表的方式:
- 一种是按照 range 来分,就是每个库一段连续的数据,这个一般是按比如时间范围来的, 但是这种一般较少用,因为很容易产生热点问题,大量的流量都打在最新的数据上了。
- 或者是按照某个字段 hash 一下均匀分散,这个较为常用。
range 来分,好处在于说,扩容的时候很简单,因为你只要预备好,给每个月都准备一个库就 可以了,到了一个新的月份的时候,自然而然,就会写新的库了;缺点,但是大部分的请求, 都是访问最新的数据。实际生产用 range,要看场景。
hash 分发,好处在于说,可以平均分配每个库的数据量和请求压力;坏处在于说扩容起来比较 麻烦,会有一个数据迁移的过程,之前的数据需要重新计算 hash 值重新分配到不同的库或表。