分库分表技术详解:从入门到实践

前言

作为一名后端开发者,当你的系统用户量越来越多,数据库压力越来越大时,你一定会遇到"分库分表"这个概念。本文将用通俗易懂的方式,帮助小白开发者理解为什么需要分库分表,以及它能解决什么问题。

一、什么是分库分表?

1.1 核心概念

在大规模分布式系统中,单一数据库实例往往成为系统扩展的瓶颈。分库分表作为一种数据库水平扩展策略,通过将数据分散存储到多个物理节点上,从而突破单机存储和性能限制。

从系统架构角度看,分库分表本质上是一种数据分片(Sharding)策略,其核心思想是将原本集中式的数据存储改造为分布式存储架构,通过增加节点数量实现线性扩展能力。

1.2 技术定义

  • 分库(Database Sharding):将一个数据库拆分成多个独立的数据库
  • 分表(Table Sharding):将一张大表拆分成多张小表
  • 垂直拆分:按业务功能拆分(如用户表、订单表分到不同库)
  • 水平拆分:按数据行拆分(如用户表按ID范围分成多张表)

二、为什么需要分库分表?

2.1 单库单表的性能瓶颈

问题1:存储容量有限
复制代码
MySQL单表建议:
- 数据量 < 2000万行
- 单表文件大小 < 10GB
超过这个量级,查询性能会显著下降

真实案例:某电商平台订单表,每天新增100万订单,一年就是3.65亿条数据,单表早已无法承受。

问题2:查询性能下降
sql 复制代码
-- 在千万级数据表中查询
SELECT * FROM orders WHERE user_id = 12345;
-- 即使有索引,也可能需要扫描大量数据块

数据对比

数据量 B+树层级 查询耗时
100万 3层 10ms
1000万 4层 50ms
1亿 5层 200ms+
问题3:并发压力大
复制代码
单数据库连接数限制:
- MySQL默认最大连接数:151
- 高并发场景:10000+ QPS
- 结果:连接池耗尽,请求排队或超时
问题4:备份恢复困难
  • 单库100GB数据,全量备份需要数小时
  • 故障恢复时间过长,影响业务连续性

2.2 分库分表的核心价值

价值1:提升性能
复制代码
分表前:1亿数据查询 → 200ms
分表后:1000万/表 × 10张表 → 20ms
性能提升:10倍
价值2:横向扩展
复制代码
传统方式(纵向扩展):
- 升级服务器硬件(CPU、内存、磁盘)
- 成本高,有上限

分库分表(横向扩展):
- 增加服务器数量
- 成本低,理论无上限
价值3:高可用保障
复制代码
单库架构:
数据库宕机 → 整个系统不可用

分库架构:
某个库宕机 → 只影响部分用户(如1/10)

三、分库分表的具体方案

3.1 垂直拆分

垂直分库

场景:不同业务模块的数据分离

复制代码
拆分前:
[单一数据库]
├── users(用户表)
├── orders(订单表)
├── products(商品表)
└── payments(支付表)

拆分后:
[用户中心DB]          [订单中心DB]          [商品中心DB]
├── users            ├── orders            ├── products
└── user_profiles    └── order_items       └── inventory

优点:
✓ 业务解耦,独立维护
✓ 故障隔离
✓ 便于微服务改造

缺点:
✗ 跨库JOIN困难
✗ 分布式事务复杂
垂直分表

场景:大字段拆分

go 复制代码
// 拆分前:用户表字段过多
type User struct {
    ID          int64
    Username    string
    Password    string
    Email       string
    Avatar      []byte    // 头像(大字段)
    Description string    // 个人简介(大字段)
    CreateTime  time.Time
    UpdateTime  time.Time
}

// 拆分后
// 主表:高频访问字段
type User struct {
    ID         int64
    Username   string
    Email      string
    CreateTime time.Time
}

// 扩展表:低频访问字段
type UserProfile struct {
    UserID      int64
    Avatar      []byte
    Description string
    UpdateTime  time.Time
}

// 优点:减少IO,提升查询速度

3.2 水平拆分

水平分表

场景:单表数据量过大

方案1:范围分片(Range-Based Sharding)

按数据的连续区间进行分片,常见维度包括:

  • 主键ID范围(如:0-1000万、1000万-2000万)
  • 时间范围(如:按月、按季度、按年)
  • 地理区域(如:华北、华东、华南)

路由策略

复制代码
分片规则映射表:
Range 1: [0, 10000000) → Shard_0
Range 2: [10000000, 20000000) → Shard_1
Range 3: [20000000, 30000000) → Shard_2

适用场景

  • 时序数据(日志、监控指标)
  • 具有明显区间特征的业务(区域分布)
  • 需要频繁进行范围查询的场景

优势与局限

  • ✓ 范围查询效率高,无需跨片扫描
  • ✓ 扩容操作简单,仅需新增分片
  • ✗ 数据分布可能不均(数据倾斜问题)
  • ✗ 热点数据集中(新增数据通常落在最新分片)

方案2:哈希分片(Hash-Based Sharding)

通过哈希算法将数据均匀分散到各分片,最常用的是取模算法。

路由策略

复制代码
算法:shard_id = hash(sharding_key) % shard_count

示例:
user_id: 12345 → hash(12345) % 10 = 5 → Shard_5
user_id: 98765 → hash(98765) % 10 = 5 → Shard_5
user_id: 11111 → hash(11111) % 10 = 1 → Shard_1

适用场景

  • 数据访问无明显热点
  • 以单条记录查询为主的业务
  • 要求数据均匀分布的系统

优势与局限

  • ✓ 数据分布均匀,避免热点问题
  • ✓ 实现简单,路由逻辑清晰
  • ✗ 范围查询需全表扫描(跨所有分片)
  • ✗ 扩容成本高(需重新计算哈希并迁移数据)

方案3:一致性哈希(Consistent Hashing)

通过哈希环实现的分布式哈希算法,核心优势是动态扩缩容时仅需迁移少量数据。

算法原理

复制代码
1. 将哈希值空间映射为环形结构(0 ~ 2^32-1)
2. 将各物理节点映射到环上的某个位置
3. 数据按顺时针方向找到第一个节点作为存储位置
4. 引入虚拟节点解决数据倾斜问题

适用场景

  • 分布式缓存系统(Redis Cluster、Memcached)
  • 需要频繁扩缩容的动态集群
  • 对数据迁移成本敏感的场景

优势与局限

  • ✓ 扩缩容时数据迁移量最小(理论上仅1/N)
  • ✓ 具备良好的容错能力(节点故障影响范围小)
  • ✗ 实现复杂度较高
  • ✗ 需要引入虚拟节点机制保证均匀性
水平分库

场景:单库连接数、IO瓶颈

多维度路由策略

在既分库又分表的架构中,需要设计两级路由算法。

复制代码
架构示意:
[DB_0]          [DB_1]          [DB_2]
├── orders_0    ├── orders_0    ├── orders_0
└── orders_1    └── orders_1    └── orders_1

路由规则(二次取模):
第一级:确定目标数据库
  db_index = sharding_key % database_count

第二级:确定目标表
  table_index = (sharding_key / database_count) % table_count

路由示例:
sharding_key: 12345, database_count: 3, table_count: 2
→ db_index = 12345 % 3 = 0 → DB_0
→ table_index = (12345 / 3) % 2 = 1 → orders_1
→ 最终路由:DB_0.orders_1

分库分表组合策略

策略组合 适用场景 特点
分库不分表 单表数据量可控,但并发压力大 提升并发能力、隔离故障
分表不分库 存储瓶颈明显,并发压力一般 降低单表数据量、提升查询效率
既分库又分表 大规模高并发场景 全方位扩展能力、复杂度最高

四、分库分表带来的挑战

4.1 分布式主键问题

问题描述:在分库分表架构中,传统的数据库自增主键机制失效,不同分片中的自增ID会产生冲突。系统需要一种全局唯一的ID生成机制。

核心需求

  • 全局唯一性(Globally Unique)
  • 趋势递增性(Sortable)
  • 高性能(High Performance)
  • 高可用(High Availability)

主流解决方案对比

方案1:雪花算法(Snowflake Algorithm)

Twitter开源的分布式ID生成算法,通过64位整数保证全局唯一。

结构组成

复制代码
64位ID结构:
| 1位符号位 | 41位时间戳 | 10位机器标识 | 12位序列号 |
|    0     |  毫秒级  | 最多1024台 | 每毫秒4096个ID |

理论性能:单机QPS = 4096 × 1000 = 409万/秒

技术特性

  • ✓ 趋势递增,对B+树索引友好
  • ✓ 本地生成,无网络依赖,性能极高
  • ✓ 包含时间戳,可反向解析生成时间
  • ✗ 依赖系统时钟,时钟回拨会导致ID重复
  • ✗ 机器ID需要提前分配和管理

适用场景:高并发订单、消息、事件等需要趋势递增ID的业务

方案2:号段模式(Segment Allocation)

通过中心化的号段分发服务批量分配ID区间。

工作原理

复制代码
1. 中心服务维护各业务类型的当前最大ID
2. 应用启动时批量获取号段(如:[1000, 2000))
3. 应用本地使用该号段,用完再申请下一段
4. 采用双Buffer机制:当前号段使用到一定阈值时,异步加载下一号段

技术特性

  • ✓ 严格递增,符合业务习惯
  • ✓ 数据库压力小(批量获取)
  • ✓ 简单易实现,无时钟依赖
  • ✗ 需要依赖数据库或独立服务
  • ✗ 存在单点故障风险(可通过主备解决)

适用场景:对ID连续性有要求的业务(如订单号展示)

方案3:UUID / GUID

通用唯一识别码,基于随机数或MAC地址生成128位标识。

技术特性

  • ✓ 实现简单,各语言均有标准库支持
  • ✓ 无需中心化服务,完全去中心化
  • ✗ 占用空间大(32字符或16字节)
  • ✗ 无序性导致数据库索引性能下降
  • ✗ 不可读,业务语义弱

适用场景:分布式追踪ID、幂等Token等不需要作为主键的场景

方案4:数据库多主模式

通过设置不同的自增起始值和步长实现。

配置示例

复制代码
DB_0: auto_increment_offset=0, auto_increment_increment=10
DB_1: auto_increment_offset=1, auto_increment_increment=10
DB_2: auto_increment_offset=2, auto_increment_increment=10

生成序列:
DB_0: 0, 10, 20, 30 ...
DB_1: 1, 11, 21, 31 ...
DB_2: 2, 12, 22, 32 ...

技术特性

  • ✓ 利用数据库原生能力,无需额外组件
  • ✓ 趋势递增
  • ✗ 扩容困难(步长固定)
  • ✗ ID不连续,存在空洞

适用场景:数据库实例数固定且较少的小规模分库场景

4.2 跨库JOIN问题

问题描述:在分库架构中,不同业务实体可能分布在不同物理数据库中,传统的SQL JOIN操作无法跨数据库执行,需要在应用层或中间件层解决关联查询问题。

典型场景

复制代码
场景:查询用户及其订单信息
传统架构:单库内直接JOIN
  SELECT u.name, o.amount FROM users u JOIN orders o ON u.id = o.user_id

分库架构:users表在DB_0,orders表在DB_1,无法直接JOIN

解决方案对比

方案1:应用层聚合(Application-Level Join)

核心思路:将JOIN操作拆解为多次独立查询,在应用层进行结果聚合。

实施步骤

复制代码
1. 查询主表数据(如:查询用户信息)
2. 提取关联键(如:user_id列表)
3. 批量查询关联表数据(使用IN条件)
4. 在内存中建立关联关系并组装结果

技术特性

  • ✓ 实现灵活,可控制查询策略
  • ✓ 无需数据冗余,保持数据一致性
  • ✓ 可针对性优化(如:缓存中间结果)
  • ✗ 多次网络往返,延迟增加
  • ✗ 应用层逻辑复杂度上升
  • ✗ 大批量JOIN时内存开销大

适用场景:JOIN数据量可控(百条级别)、对实时性要求高的场景

方案2:数据冗余(Data Redundancy)

核心思路:在订单等从表中冗余用户名等主表的常用字段,避免关联查询。

设计原则

复制代码
冗余字段选择标准:
✓ 读频率远高于写频率的字段
✓ 数据变更频率低的字段(如用户名)
✓ 数据体积小的字段(避免冗余大字段)
✗ 不冗余频繁变更的字段(如余额、状态)

一致性保障

  • 消息队列异步同步(最终一致性)
  • 分布式事务保障(强一致性,性能代价高)
  • 定期对账与修复机制

技术特性

  • ✓ 查询性能最优,无JOIN开销
  • ✓ 降低跨库查询复杂度
  • ✗ 存储空间冗余
  • ✗ 数据一致性维护成本高
  • ✗ 冗余字段变更需要同步更新多表

适用场景:读多写少、数据一致性要求不高的展示类查询

方案3:全局表(Global Table)

核心思路:将字典表、配置表等小表在每个物理库中都保留完整副本。

适用表特征

复制代码
✓ 数据量小(通常<10000行)
✓ 变更频率低(配置类、地区码表等)
✓ 所有业务都需要关联的基础数据

同步策略

  • 配置中心推送变更
  • Canal等工具监听binlog同步
  • 定时全量同步

技术特性

  • ✓ 查询简单,与单库一致
  • ✓ 无需跨库JOIN
  • ✗ 数据同步延迟
  • ✗ 存储空间浪费(N倍冗余)

适用场景:系统字典、配置参数、地理区域等基础数据表

方案4:中间件支持(Middleware Proxy)

部分分库分表中间件(如ShardingSphere)提供跨分片JOIN支持。

实现机制

复制代码
1. 中间件将SQL路由到所有相关分片
2. 收集各分片的查询结果
3. 在中间件层进行内存JOIN和聚合
4. 返回最终结果给应用

技术特性

  • ✓ 对应用透明,SQL语法兼容
  • ✗ 性能开销大(全表扫描)
  • ✗ 不适用于大数据量JOIN

适用场景:仅用于小数据量的报表查询、管理后台等非核心场景

4.3 分布式事务问题

问题描述:在分库分表架构中,单一业务操作可能涉及多个物理数据库,传统的ACID事务无法跨库保证,需要采用分布式事务解决方案。

典型场景

复制代码
电商下单流程:
1. 订单库:创建订单记录
2. 库存库:扣减商品库存
3. 账户库:扣减用户余额

要求:三个操作必须原子性完成(要么全成功,要么全失败)

CAP理论约束

在分布式系统中无法同时满足一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance),实践中通常选择牺牲强一致性以换取高可用。

解决方案对比

方案1:最终一致性(Eventual Consistency)+ 可靠消息

核心思路:通过消息队列实现异步解耦,保证最终所有操作都会成功执行。

实施模式

复制代码
本地消息表方案:
1. 订单服务在本地事务中同时写入:订单记录 + 待发送消息
2. 定时任务扫描消息表,将消息发送到MQ
3. 库存服务、账户服务消费消息并执行各自的本地事务
4. 消费失败时进行重试(幂等性保障)
5. 最终所有服务都完成操作,达到最终一致性

技术特性

  • ✓ 性能高,无阻塞等待
  • ✓ 可用性高,服务解耦
  • ✓ 易于水平扩展
  • ✗ 数据一致性存在延迟(通常秒级)
  • ✗ 需要处理消息重复、顺序等问题
  • ✗ 业务逻辑需要容忍中间状态

适用场景:互联网高并发业务、对实时一致性要求不严格的场景(推荐)

方案2:两阶段提交(2PC - Two-Phase Commit)

核心思路:引入事务协调器,通过准备和提交两个阶段保证强一致性。

执行流程

复制代码
阶段一:准备阶段(Prepare)
1. 协调器向所有参与者发送Prepare请求
2. 参与者执行事务但不提交,返回Yes/No
3. 协调器收集所有参与者的投票结果

阶段二:提交阶段(Commit)
1. 若所有参与者返回Yes,协调器发送Commit命令
2. 若任一参与者返回No,协调器发送Rollback命令
3. 参与者执行命令并返回确认

技术特性

  • ✓ 强一致性保障
  • ✓ 符合传统事务语义
  • ✗ 同步阻塞,性能差(RT提高数倍)
  • ✗ 单点故障风险(协调器)
  • ✗ 脑裂场景下可能数据不一致

适用场景:金融核心系统等对数据一致性要求极高的场景(慎用)

方案3:TCC模式(Try-Confirm-Cancel)

核心思路:将业务操作拆分为三个阶段,由业务代码保证一致性。

三阶段说明

复制代码
Try阶段:资源预留
  - 检查资源是否充足
  - 预留所需资源(如:冻结库存、冻结金额)
  - 记录操作日志

Confirm阶段:执行业务
  - 使用已预留的资源完成业务操作
  - 释放资源锁定

Cancel阶段:回滚补偿
  - 释放Try阶段预留的资源
  - 恢复到操作前状态

实施示例

复制代码
下单场景TCC设计:
Try:
  - 订单服务:创建"预下单"记录
  - 库存服务:冻结库存(available_stock -= 1, frozen_stock += 1)
  - 账户服务:冻结余额(available_balance -= 100, frozen_balance += 100)

Confirm:
  - 订单服务:将订单状态改为"已下单"
  - 库存服务:扣减冻结库存(frozen_stock -= 1)
  - 账户服务:扣减冻结余额(frozen_balance -= 100)

Cancel:
  - 订单服务:删除预下单记录
  - 库存服务:释放冻结库存(available_stock += 1, frozen_stock -= 1)
  - 账户服务:释放冻结余额(available_balance += 100, frozen_balance -= 100)

技术特性

  • ✓ 无长时间锁等待,性能优于2PC
  • ✓ 适应复杂业务场景
  • ✗ 实现复杂度高,需要业务侵入
  • ✗ 需要设计反向补偿操作
  • ✗ 对幂等性要求高

适用场景:金融支付、库存扣减等资金类、库存类核心业务

方案4:SAGA模式

核心思路:将长事务拆分为多个本地短事务,每个短事务都有对应的补偿事务。

执行模式

复制代码
协同式SAGA(Choreography):
  服务间通过事件驱动进行协作,无中心协调器

编排式SAGA(Orchestration):
  由中心编排器负责协调各服务的执行顺序

技术特性

  • ✓ 适合长流程业务(如旅游订单:机票+酒店+接送)
  • ✓ 事务颗粒度灵活
  • ✗ 需要设计补偿逻辑
  • ✗ 不保证隔离性(脏读问题)

适用场景:微服务架构下的跨服务长流程事务

方案选型建议

场景特征 推荐方案 原因
互联网高并发业务 最终一致性 性能优先,容忍短暂不一致
金融核心业务 TCC 平衡性能与一致性
银行转账清算 2PC 强一致性要求
跨服务长流程 SAGA 灵活性与容错性
非核心辅助业务 最大努力通知 实现简单,成本低

4.4 数据迁移问题

问题描述:在已有业务系统中引入分库分表,需要在不停服的前提下完成海量数据迁移,同时保证数据一致性和业务连续性。

核心挑战

  • 存量数据迁移(TB级数据)
  • 增量数据同步(实时写入)
  • 业务切换无感知(零停机)
  • 数据一致性校验

平滑迁移方案

阶段1:双写策略(Dual Write)

复制代码
架构状态:
应用层 ─┬─> 旧库(主写主读)✓ 保证业务连续性
        └─> 新库(从写)      ✓ 积累新增数据

实施要点:
- 新库写入失败不影响主流程(异步 + 日志记录)
- 记录双写开始时间点,作为数据对账基准
- 监控双写成功率,确保数据完整性

阶段2:历史数据迁移(Data Migration)

复制代码
迁移策略:
1. 分批迁移:按分片键范围分批导出导入(每批10万-100万行)
2. 并行迁移:多线程/多进程并行处理不同分片
3. 限速控制:避免对生产库造成压力(限制QPS、IO)
4. 断点续传:记录迁移进度,支持中断恢复

工具选型:
- Canal:监听MySQL binlog实时同步
- DataX:阿里开源的离线数据同步工具
- 自研脚本:SELECT + INSERT批量迁移

阶段3:数据校验(Data Validation)

复制代码
校验维度:
- 数据总量对比:count(*) 统计
- 关键业务数据抽样:随机抽取10%数据对比字段值
- 数据完整性:校验主键连续性、外键关联
- 业务指标对比:订单金额、用户数等核心指标

自动化对账:
- 定时任务扫描差异数据
- 不一致数据自动修复或告警
- 记录对账日志供审计

阶段4:读流量切换(Read Traffic Switch)

复制代码
灰度切换策略:
1. 灰度1%:少量用户读新库,观察监控指标
2. 灰度10%:扩大范围,持续观察
3. 灰度50%:半数流量切换
4. 全量100%:完全切换到新库

快速回滚机制:
- 保留旧库数据
- 配置中心动态切换读库
- 异常情况秒级回滚

阶段5:下线旧库(Decommission)

复制代码
清理步骤:
1. 停止双写:仅写新库
2. 保留观察期:保留旧库1-3个月用于应急
3. 数据归档:将旧库数据归档到冷存储
4. 资源回收:释放旧库服务器资源

关键风险与应对

风险点 应对措施
迁移过程数据不一致 双写 + binlog同步 + 自动对账
切换过程业务中断 灰度切换 + 快速回滚
性能下降 压测验证 + 监控告警
数据丢失 全量备份 + 增量备份

五、典型业务场景设计

5.1 电商订单表分片设计

业务特征分析

  • 数据规模:日订单量100万,年订单量3.65亿
  • 查询模式:95%按用户ID查询历史订单,5%按订单号查询
  • 写入特征:高并发写入,峰值QPS达10000+
  • 存储周期:热数据2年,冷数据归档

分片策略选择

方案对比

维度 按时间分片 按用户ID Hash分片 选择
查询效率 范围查询慢 单用户查询快 ✓ Hash
数据分布 不均匀(新表热) 均匀 ✓ Hash
扩容难度 简单(新增月表) 需数据迁移 -
业务匹配 不符合(按用户查询为主) 符合 ✓ Hash

最终设计

复制代码
分片策略:按user_id哈希分表
分片数量:32张表(2的幂次,便于未来扩展到64/128)
路由算法:table_index = user_id % 32
表命名:orders_0, orders_1, ..., orders_31

核心表结构:
- order_id: BIGINT(雪花算法生成,全局唯一)
- user_id: BIGINT(分片键,建立索引)
- create_time: DATETIME(辅助索引,用于时间范围查询)
- amount: DECIMAL(订单金额)
- status: TINYINT(订单状态)

索引设计:
- PRIMARY KEY (order_id)
- INDEX idx_user_create (user_id, create_time) -- 组合索引,覆盖常用查询
- INDEX idx_status (status) -- 状态查询索引

查询场景适配

复制代码
场景1:查询用户订单列表(高频)
  - 直接路由到目标表:orders_{user_id % 32}
  - 单表查询,性能优异
  
场景2:按订单号查询(低频)
  - 方案A:全表扫描(32张表并行查询)
  - 方案B:订单号中包含分片信息(推荐)
    如:订单号 = 时间戳 + 分片号 + 序列号
    
场景3:商家查询所有订单(后台管理)
  - 使用ES等搜索引擎异步同步
  - 避免跨分片查询影响核心业务

性能提升数据

指标 分表前 分表后(32表) 提升
单表数据量 3.65亿 1140万/表 减少97%
用户订单查询RT 180ms 15ms 提升12倍
写入吞吐QPS 3000 30000+ 提升10倍
磁盘IO使用率 85% 25% 降低71%

5.2 社交平台用户表分库分表设计

业务特征分析

  • 数据规模:总用户量2亿,日活5000万
  • 并发模式:读QPS 80000,写QPS 5000
  • 查询模式:99%按用户ID精确查询
  • 扩展需求:预计3年内用户量翻倍

架构设计

复制代码
总体方案:4库 × 16表 = 64个分片

第一级路由(库):db_index = user_id % 4
第二级路由(表):table_index = (user_id / 4) % 16

分片映射示例:
user_id: 12345
  → db_index = 12345 % 4 = 1 → DB_1
  → table_index = (12345 / 4) % 16 = 8 → users_8
  → 最终路由:DB_1.users_8

拆分收益:
- 单库并发:80000 / 4 = 20000 QPS(可承受)
- 单表数据量:2亿 / 64 = 312万/表(健康水平)
- 连接数分散:每库独立连接池,避免连接耗尽

垂直拆分优化

复制代码
主表(高频访问):user_base
- user_id, username, mobile, status, create_time
- 存储核心身份信息,轻量化

扩展表(低频访问):user_profile
- user_id, avatar_url, bio, location, birthday
- 存储详细资料,按需查询

统计表(独立维护):user_stats
- user_id, followers_count, following_count, posts_count
- 计数器字段,高频更新,独立分片避免锁竞争

六、最佳实践建议

6.1 何时需要分库分表?

触发条件(满足任一即可考虑):

复制代码
✓ 单表数据量 > 1000万
✓ 单表文件大小 > 5GB
✓ 查询响应时间 > 100ms
✓ 数据库连接数接近上限
✓ 磁盘IO持续 > 80%

不要过早优化

  • 初创项目、用户量 < 10万:单表完全够用
  • 优先通过索引、缓存优化
  • 只有遇到明确瓶颈时再考虑分库分表

6.2 设计原则

1. 选好分片键(Sharding Key)

复制代码
✓ 查询高频字段(如user_id)
✓ 数据分布均匀
✓ 尽量避免跨片查询

✗ 不要选时间字段(数据倾斜)
✗ 不要选低基数字段(如性别)

2. 预留扩展空间

go 复制代码
// 设计表数量时,建议2的幂次
// 方便未来翻倍扩容
tableCount := 16 // 将来可扩展到32、64

3. 保持表结构一致

sql 复制代码
-- 所有分表结构必须完全一致
-- 使用统一的DDL脚本管理

4. 避免分布式事务

复制代码
✓ 业务上拆分,避免跨库操作
✓ 使用最终一致性代替强一致性
✗ 尽量不用两阶段提交
相关推荐
IUGEI1 小时前
【后端开发笔记】JVM底层原理-内存结构篇
java·jvm·笔记·后端
i***39582 小时前
Springboot中SLF4J详解
java·spring boot·后端
子洋2 小时前
群晖 DSM 更新后 Cloudflare DDNS 失效的排查记录
前端·后端·dns
z***94842 小时前
springboot和springframework版本依赖关系
java·spring boot·后端
p***95002 小时前
spring Profile
java·数据库·spring
一 乐2 小时前
宠物管理宠物医院管理|基于Java+vue的宠物医院管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·宠物
一 乐2 小时前
学习辅导系统|数学辅导小程序|基于java+小程序的数学辅导小程序设计与实现(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·学习·小程序
励志成为糕手2 小时前
基于SpringBoot的企业考勤管理系统设计与实现
java·spring boot·后端·web·企业应用
Olafur_zbj2 小时前
【AI】使用OCR处理pdf
数据库·pdf·ocr