配合视频效果更佳:www.itlaoqi.com/chapter.htm…
什么是垂直分表
你是否遇到过这种情况,在工作中尤其在银行经常遇到一个表上百个字段,好像这已经变成习以为常的事情了。
但这样做真的没问题吗?
十多年前我也这么认为的,但现在的我觉得那时真的太菜了。这种数据是必须要做垂直分表的,否则系统处理过程简直就是一种灾难,那什么是垂直分表呢?这样和水平分表来比较。
水平分表是按行对数据进行拆分,一般意义上的分库分表就是“水平分表”,水平分表是将数据库按某种分片算法(范围法、Hash法)将记录分别存放到不同的表中,通过大表拆小表的方式缩小数据查询范围,提高处理效率,水平分表最显著的特点是所有分表的表结构都是完全相同的。
而垂直分表则是代表将一张大表按“列”拆分为2张以上的小表,通过主外键关联来获取数据。
为什么要垂直分表
以下图文理,我们把一张大的商品表且分为基本信息表与详情信息表,通过商品id做1对1关联
SQL语句也相应变为
#调整前
SELECT * FROM 商品表 WHERE 商品标题='AD钙奶';
#调整后
SELECT * FROM 商品基本信息表 a,商品详情表 b WHERE a.商品id=b.商品id and a.商品标题='AD钙奶';
此时不明真相的群众已经开始骂娘了,你这不是玩我们么,一张表能解决的事为啥要拆成2个表?
其实这要从MySQL Innodb存储引擎的机制说起,在Innodb中,存储数据的基本单位为“行(Row)“,管理数据的基本单位位“页(Page)“,MySQL中默认每一页都是固定的16K大小,一页内允许存储某一张表的若干行数据,页内部数据存储是紧密的,检索效率非常高。在MySQL中用于保存页的单位被称为“区(Extent)”,区由连续的页组成,默认情况下一个区有1MB的存储空间,也就是一个区默认最多可以有64个连续的页,从Innodb1.0开始,因为引入了压缩页这些新特性,从存储空间上页实际占用的空间会更少,但也带来新问题,因为压缩解压缩都要占用CPU与IO资源,在跨页检索时数据就没有页内提取时效率那么高了,所以在数据表设计的时候,要尽可能保证每一页尽可能多存储一些行,这样检索效率会更高,这是设计优化的理论支撑。
还是以商品表为例,如果不做垂直切分,假设平均一条数据占用1K,一页最多也只能装16条,如果有1亿条数据,数据就要被分散到625万页上,这个数据处理效率肯定不会太好。
但是如果垂直节分后,基础信息表只包含最重要的几个基础字段,而描述信息被包含在详情信息表。假设当下基础信息表每行只占用 64字节,那基础信息页只需要39万页就可以保存所有基础信息。
当数据范围被缩小后,优势便非常明显,还是以刚才的SQL距离。
#调整前
SELECT * FROM 商品表 WHERE 商品标题='AD钙奶';
#调整后
SELECT * FROM 商品基本信息表 a,商品详情表 b WHERE a.商品id=b.商品id and a.商品标题='AD钙奶';
调整前SQL阴差阳错这个商品标题没有应用到索引,那MySQL就要在物理层面上数据就要扫描625万页。
调整后通过关联查询的逻辑就不一样了,首先查询时商品基本信息表被作为驱动表,同样情况下物理层面上数据就要扫描39万页,这个扫描的量级相差了16倍,处理效率上绝对有肉眼可见的区别。
之后扫描后获取到商品id,再通过详情表的商品id主键索引快速定位提取对应详情数据进行返回。
看到上面的案例后,相比你已经理解“垂直分表”的用意。通过将重要字段单独剥离出一张小表,让每一页能够容纳更多的行,进而缩小数据扫描的范围,达到提高执行效率的目的。
垂直分表的依据有哪些
垂直分表是对于多字段大表的优化措施,通常要满足以下两个条件:
- 单表数据量未来可能千万
- 字段超过20个,且包含了超长的Varchar、CLOB、BLOB等字段
那哪些字段应该放在小表,哪些应剥离到大表
- 在MySQL处理时,一定要谨记小表驱动大表的规则
- 小表应保留重要字段,这里的重要字段包含两类:
- 数据查询、排序时需要的字段,如分类编号、商户id、品牌编号、逻辑删除标志位等
- 高频访问的小字段,如商品名称、子标题、价格、厂商基本等
- 相对的,有两类字段应被划分在大表中
- 低频访问字段:配送信息、售后声明、最后更新时间等
- 大字段:商品图文详情、图片BLOB、JSON元数据等
以上就是垂直分表从入门到原理,再到应用的介绍,希望能对你有帮助。