问题

什么是分库分表?

答案

1. 核心概念

分库分表是一种数据库水平扩展方案,通过将单个数据库或表的数据拆分到多个数据库或表中,来解决单库单表的性能瓶颈和存储容量限制问题。

分为两个维度:

  • 分库(Database Sharding):将数据分散到多个数据库实例中,分摊单库的并发压力和连接数
  • 分表(Table Sharding):将单表数据分散到多个表中,降低单表数据量,提升查询性能

2. 分库分表的分类

2.1 垂直拆分

  • 垂直分库:按业务模块将不同的表拆分到不同的数据库中
    • 例如:将用户库、订单库、商品库拆分为独立的数据库
    • 优点:业务隔离,降低耦合,便于维护
  • 垂直分表:将表中的字段拆分到多个表中
    • 例如:将用户表拆分为用户基本信息表和用户扩展信息表
    • 优点:减少单表字段数,适合大字段或低频字段的分离

2.2 水平拆分

  • 水平分库:将同一张表的数据按某种规则分散到多个数据库中
    • 例如:按用户ID范围或哈希值分配到不同的数据库
  • 水平分表:将同一张表的数据按某种规则分散到多个表中
    • 例如:order_0, order_1, order_2…
    • 优点:降低单表数据量,提升查询和写入性能

3. 为什么需要分库分表

问题类型 说明 解决方案
单表数据量过大 千万级数据导致查询变慢,索引失效 水平分表
并发压力大 单库连接数有限,CPU/IO成为瓶颈 水平分库
磁盘容量不足 单机存储空间有限 水平分库
业务耦合严重 不同业务共用一个库,相互影响 垂直分库

4. 示例场景

假设有一个订单表 order,数据量达到1亿条:

-- 原始单表结构
CREATE TABLE order (
    order_id BIGINT PRIMARY KEY,
    user_id BIGINT,
    product_id BIGINT,
    amount DECIMAL(10,2),
    create_time DATETIME
);

水平分表方案:按 order_id 取模拆分为16张表

// 分表路由算法
public String getTableName(Long orderId) {
    int tableIndex = (int) (orderId % 16);
    return "order_" + tableIndex;  // order_0 ~ order_15
}

水平分库方案:按 user_id 哈希分配到4个数据库

// 分库路由算法
public String getDatabaseName(Long userId) {
    int dbIndex = Math.abs(userId.hashCode() % 4);
    return "db_" + dbIndex;  // db_0 ~ db_3
}

5. 核心要点总结

  1. 分库分表是解决单库单表性能瓶颈的有效手段,主要应对高并发和大数据量场景
  2. 垂直拆分关注业务隔离,水平拆分关注数据量和并发分摊
  3. 分库解决并发和存储问题,分表解决单表数据量问题
  4. 实际应用中常常结合使用:先垂直分库(按业务),再水平分表(按数据量)
  5. 分库分表会引入新的复杂性:分布式事务、跨库查询、全局ID生成等问题需要配套解决方案