在数据库设计中,如果单张表的数据量过大,会导致查询很慢,这时候就要考虑对表的拆分,常见拆分方式有两种,水平分表和垂直分表。
水平分表:
数据库水平分表指数据库按照某种算法,常见的有范围法,HASH法,将数据存在不同表中。
范围法:根据数据条数进行分表存储,举例:ID为1亿-2亿的数据存一张表,3亿到4亿的数据存一张表。
HASH法:按照ID取模,将数据均匀进行分配。
水平分表的特点是所有数据的表结构都是完全一样的。
解决的是数据量大的存储问题。
垂直分表:
垂直分表是将一张大表按照‘列’才分为2张或多张的小表,通过主外键关联来获取数据。
以商品表为例,商品表的字段可以按照下图的方式,拆分为两张表:商品基本信息表、商品详情信息表。
通过垂直分表的操作,查询SQL也会发生变化,如上图所示,拆表前,只需要查询单张表就可以完成,拆表后要进行表关联,来达到查询的目的。
为何要做垂直分表,则需要明白数据库的存储原理。以mysql的innerDB引擎为例:
一行一行的数据,被成为row。
管理数据的基本单位为page(页),默认大小16KB,作为mysql中保存page的基本单位称作Extent(区),一个区由连续的页组成,默认一个区有1M的存储空间,即一个区可以连续装载64个页。每一页中,根据数据的大小,可以存储多行数据。
在innerDB的1.0以后,引入了新特性,压缩页,也就是对页进行压缩,让实际存储小于逻辑存储。有压缩也就有解压缩。
在设计表时尽量保证,每一页内尽可能多存储一些行数据,这样可以减少跨页检索,尽可能提高页内数据的检索效率。
以上是优化数据库的理论支撑。
再回到示例中的商品表,假如有1亿数据量的商品信息。
不拆表:全部数据都存储在一张表中,如果一行数据有1K,大概需要625万页来进行存储。
拆表:将重要的基础字段放到商品基本信息表中,其他的多个描述信息字段,放到商品详情信息表中。
这样拆分以后,假如商品基本信息表,每一行数据大小为64字节。1亿数据,只需要39万页就可以将数据完整存储。
拆分后,在对商品基本信息表的扫描,只需要对39万页的内容进行扫描,与未拆分表的625万页相比,少了16倍,差距是非常大的。
快速扫描后,会定位到商品ID,再通过商品ID主键索引,去商品详情表中将对应数据进行提取,从而提升查询效率。
总结:通过将总要字段单独剥离出来一张小表,让每一页能容纳更多的行,进而缩小数据扫描的范围,达到提高执行效率的目的。
垂直分表原则:
1.单表数据量未来可能为千万级。
2.表字段超过20个,且包含了超长的varchar、CLOB、BLOB等大数据字段类型。
如果满足以上两个条件,可以考虑进行垂直分表。
表字段拆分原则:
1.小表字段(示例中的商品基本信息表):
数据查询、排序时需要的字段,如分类编号、商品ID、商品编号、逻辑删除标志位。
高频访问的小字段,如商品名称、子标题、价格、厂商基本等。
2.大表字段(示例中的商品详情信息表):
低频访问字段:配送信息、售后声明、最后更新时间等。
大数据字段:商品图文详情、图片BLOB、JSON元数据等。
大字段可能拆分为多张表,示例中只是拆分为两张表,根据实际情况,可能拆分为多张表,来达到优化数据存储的目的。