一、为什么要进行分库分表?
分库分表的目的是为了解决单表过大、单库表过多的问题,具体可参考文章(《如何进行SQL调优?》)
二、什么情况下需要进行分库分表?
以下几种情况可以考虑分库分表:
- 单表数据量达到千万级别(读写性能差)
- 数据库中内存占用率高
- 业务并发场景多
三、如何进行分库分表?
1、分库
分库主要是为了解决单库数据量大、请求并发量大的问题。
一般的分库方案有:
- 垂直分库:根据业务使用场景进行分库,如订单库、用户库、商品库等
- 水平分库:根据同一张表进行哈希从而分散到不同库中,减少单库性能瓶颈
2、分表
分表主要是为了解决单表数据量大的问题。
一般的分表方案有:
- 垂直分表:将同一张表中通过列来拆分,将关联度比较高的列放在一起方便查询,如用户信息表可拆分为用户基本信息表和用户扩展信息表
- 水平分表:根据同一张表进行哈希从而分散到不同表中,减少单表性能瓶颈
同时水平分表也分为两种方式:
- 主键id分表:适用于等值查询、状态维护的场景,如用户表(
user1
、user2
…) - 范围分表:适用于范围查询的场景,如流水表可用插入时间来分表(
history202301
、history202302
…)
三、分库分表会带来什么问题?
分库分表虽然可以提高读写性能,但是还会带来以下几个问题:
- 不支持跨库事务:只能通过分布式事务来解决(具体可参考文章《什么是分布式事务?》)
- 重复ID:在单表中由于有自增ID,所以是不会出现重复ID的问题。而在分库分表后如果还是用自增ID,那么是会出现重复ID的问题,所以我们要通过分布式id来解决(具体可参考文章《如何设计分布式ID?》)
- 不支持反向查询:如果我们用了主键id分表,我们通过主键id来做查询/范围查询都是没有问题的,但是如果我们要通过关联id来反向做查询/范围查询都会出现问题(如
attention1
中存了用户的关注记录,但是我们没办法在该表上查询用户的所有被关注记录)。所以我们可以考虑用冗余数据表的方式来解决(主要还是一个空间换时间的思想,比如关注表可以冗余一份被关注表来辅助查询,相似的还有买家表对应卖家表等) - 不方便扩容:比如我们的用户表分了10个表,过了一段时间用户数据量扩大了100倍,那么我们用原先的10个分表是可能会有性能瓶颈问题的,只能通过扩容+重新哈希+旧数据清洗的方式解决(相反,如用范围分表的方式就不会出现这种问题)