当单表的数据量达到1000W或100G以后,优化索引、添加从库等可能对数据库性能提升效果不明显,此时就要考虑对其进行切分了。切分的目的就在于减少数据库的负担,缩短查询的时间。
-
限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询
订单历史的时候,我们可以控制在一个月的范围内。 -
读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读;
-
垂直分区: 根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又
有用户的基本信息,可以将用户表拆分成两个单独的表,也可以利用垂直切分将经常被使用的列和
不经常被使用的列切分到不同的表中。 甚至放到单独的库做分库。简单来说垂直拆分是指数据表列
的拆分,把一张列比较多的表拆分为多张表。 如下图所示,这样来说大家应该就更容易理解了。
垂直拆分的优点: 可以使得行数据变小,在查询时减少读取的阻塞数,减少磁盘 I/O 次数。此外,
垂直分区可以简化表的结构,易于维护。
垂直拆分的缺点: 主键会出现冗余;部分表关联操作(join 操作)无法在数据库级别完成,需要在
程序中完成;此外,垂直分区会让事务变得更加复杂(我估计是因为原来直接对一个表操作就行了,
现在会多个表操作,代码量多了)。 -
水平分区(Sharding): 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据
分散到不同的表或者库中,达到了分布式的目的。 水平拆分是指数据表行的拆分,表的行数超过
200 万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用
户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。
需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器
上,其实对于提升 MySQL 并发能力没有什么意义,所以 水平拆分最好分库 。
水平切分优点:支持非常大的数据量存储,不会遇到因为数据量大产生瓶颈问题;应用端程序改造
也少。
水平切分缺点: 切分规则相对复杂,很难制定出一个满足所有查询的切分规则;分片事务一致性难
以解决 ;跨库 Join 性能较差。
通常情况下,我们使用取模的方式来进行表的拆分;比如一张有 400W 的用户表 users,为提高其查询
效率我们把其分成 4 张表 users1,users2,users3,users4 通过用 ID 取模的方法把数据分散到四张表
内 Id%4+1 = [1,2,3,4] 然后查询,更新,删除也是通过取模的方法来查询。
例:QQ 的登录表。假设 QQ 的用户有 100 亿,如果只有一张表,每个用户登录的时候数据库都要从
这 100 亿中查找,会很慢很慢。如果将这一张表分成 100 份,每张表有 1 亿条,就小了很多,比如
qq0,qq1,qq1…qq99 表。
用户登录的时候,可以将用户的 id%100,那么会得到 0-99 的数,查询表的时候,将表名 qq 跟取模
的数连接起来,就构建了表名。比如 123456789 用户,取模的 89,那么就到 qq89 表查询,查询的
时间将会大大缩短。