大表优化

Catalogue
  1. 1. 限定数据的范围
  2. 2. 读/写分离
  3. 3. 加缓存
  4. 4. 垂直分
  5. 5. 水平分
  6. 6. 分片实现

当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:

限定数据的范围

务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。

读/写分离

经典的数据库拆分方案,主库负责写,从库负责读

加缓存

使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存,如redis

垂直分

根据数据库里面数据表的相关性进行拆分。
例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。

简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。

  • 垂直拆分的优点: 可以使得一行的数据字段变少,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。
  • 垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此外,垂直分区会让事务变得更加复杂;

水平分

保持数据表结构不变,通过某种策略分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。

水平拆分是指数据表行的拆分,MySQL表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。

需要注意的一点是: 分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好分库 。

水平拆分能够 支持非常大的数据量存储,应用端改造也少,但分片事务难以解决 ,跨界点Join性能较差,逻辑复杂。

分片实现

  • 客户端代理: 分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的实现。
  • 中间件代理: 在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。 我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现。