《用单库自增键来生成id了,后期怎么分库?哎,这个坑大!》

《单KEY业务,数据库水平切分架构实践》

《1对多业务,数据库水平切分架构一次搞定》

《多对多业务,数据库水平切分架构一次搞定》

《多key业务,数据库水平切分架构一次搞定》

表垂直拆分的依据是什么

当一个表属性很多时,如何来进行垂直拆分呢?如果没有特殊情况,拆分依据主要有如下几点:

  1. 将长度较短,访问频率较高的属性尽量放在一个表里,这个表暂且称为主表;
  2. 将字段较长,访问频率较低的属性尽量放在一个表里,这个表暂且称为扩展表;
  3. 经常一起访问的属性,也可以放在一个表里;

优先考虑1和2,第3点不是必须。另,如果实在属性过多,主表和扩展表都可以有多个。

一般来说,数据量并发量比较大时,数据库的上层都会有一个服务层。需要注意的是,当应用方需要同时访问主表和扩展表中的属性时,服务层不要使用 join 来连表访 问,而应该分两次进行查询:

原因是,大数据高并发互联网场景下,一般来说,吞吐量和扩展性是主要矛盾:

  1. join 更消损耗数据库性能;
  2. join 会让 base 表和 ext 表耦合在一起(必须在一个数据库实例上),不利于数据量大时拆分到不同的数据库实例上。毕竟减少数据量,提升性能才是垂直拆分的初衷。

为什么要这么这么拆分

为何要将字段短,访问频率高的属性放到一个表内?为何这么垂直拆分可以提升性能?

原因:

  1. 数据库有自己的内存 buffer,会将磁盘上的数据 load 到内存 buffer 里;
  2. 内存 buffer 缓存数据是以 row 为单位的;
  3. 在内存有限的情况下,在数据库内存 buffer 里缓存短 row,就能缓存更多的数据;
  4. 在数据库内存 buffer 里缓存访问频率高的 row,就能提升缓存命中率,减少磁盘的访问;

举个例子就很好理解了:

假设数据库内存 buffer 为1G,未拆分的 user 表1行数据大小为1k,那么只能缓存100w行数据。

如果垂直拆分成 user_base 和 user_ext,其中:

  • user_base 访问频率高(例如 uid,name,passwd,以及一些 flag 等),一行大小为0.1k
  • user_ext 访问频率低(例如签名,个人介绍等),一行大小为0.9k

那边内存 buffer 就就能缓存近乎1000w行 user_base 的记录,访问磁盘的概率会大大降低,数据库访问的时延会大大降低,吞吐量会大大增加。

作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/slkbgz 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。