分库分表的策略
1. 主键+业务虚拟键分表
这种方式适合查询比较单一的业务,最大的缺点就是业务对分库分表这层是有感知:
- 查询返回的时候需要在接口层拼接业务的真实Id
- 根据真实业务Id查询,或者更新数据的时候,需要拆分真实业务Id,路由到数据所在表,再根据数据库Id查询
虚拟场景
假设我们分了1024张表,具体表结构如下:
插入流程
1. 插入数据,必须带有userId
2. 根据userId计算出xId
xId = userId % 10000;
3. 根据xId定位数据所在表
tNum = xId % 1024; // 最简单的取模hash(具体策略由中间件决定)
4. 插入数据,返回realId
realId = id + xId;
单条查询流程
1. 根据realId查询, 获取单张表中的Id值
id = realId / 10000; // 整除
2. 获取虚拟键xId
xId = realId % 10000;
3. 根据xId定位数据所在表
tNum = xId % 1024; // 最简单的取模hash(具体策略由中间件决定)
4. 根据表和Id获取单条数据
批量查询流程
基本和单条查询一致,可优化的点:
第3步,根据xId进行分组,将查询同一张表的query放在一次sql的查询语句中
2. 主键/业务外键分表
这种策略对业务代码可以无侵略性, 为避免Id冲突, 使用外部Id生成器, 以下步骤全在中间件中执行:
(根据业务外键的处理同理,查询比较复杂的情况一般都是使用冗余表)
虚拟场景
假设我们分了1024张表,具体表结构如下:
插入流程
1. 从Id生成器获取Id
2. 根据Id进行hash (简单的可以使用取模), 获取数据应该插入的表名
tNum = id % 1024;
3. 插入数据表
单条查询流程
1. 根据Id进行hash (简单的可以使用取模), 获取数据所在表名
tNum = id % 1024;
2. 查询数据
批量查询流程
基本和单条查询一致,可优化的点:
第1步,根据Id进行hash后进行分组,将查询同一张表的query放在一次sql的查询语句中
数据的聚合
在批量查询的时候,需要 order by
group by
distinct
的时候,需要在查询出各分表数据之后,在中间件组件中自行实现对数据的处理