跳转至
用户认证 - eMac Tech Docs

用户认证

重要提醒

为了您的权益以及学习体验,请不要外借账号!

如果您没有账号或忘记密码,请联系管理员重置密码。

请输入您的登录信息

MySQL水平分表

水平分表概述

1. 什么是水平分表

graph TD
    app[应用服务器]
    shard1[分片1]
    shard2[分片2]
    shard3[分片3]
    app -->|数据路由| shard1
    app -->|数据路由| shard2
    app -->|数据路由| shard3

水平分表是将同一个表的数据按照某种规则分散到多个物理表中,每个表的结构相同。

2. 水平分表的优势

  • 提高查询性能
  • 减少单表数据量
  • 提高并发能力
  • 便于维护管理

分片策略

1. 范围分片

-- 按ID范围分片
CREATE TABLE orders_1 (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_2 (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

-- 分片规则:id <= 1000000 在orders_1,id > 1000000 在orders_2

2. 哈希分片

-- 按用户ID哈希分片
CREATE TABLE orders_0 (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_1 (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

-- 分片规则:user_id % 2 决定分片

3. 时间分片

-- 按时间分片
CREATE TABLE orders_202301 (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_202302 (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

-- 分片规则:按月份分片

实现方式

1. 应用层实现

// 分片路由
public class OrderShardingStrategy {
    public String getTableName(Long orderId) {
        return "orders_" + (orderId % 2);
    }

    public String getTableNameByUserId(Long userId) {
        return "orders_" + (userId % 2);
    }
}

// 数据访问
@Service
public class OrderService {
    @Autowired
    private OrderShardingStrategy shardingStrategy;

    public void saveOrder(Order order) {
        String tableName = shardingStrategy.getTableName(order.getId());
        // 插入对应分片表
    }

    public Order getOrder(Long orderId) {
        String tableName = shardingStrategy.getTableName(orderId);
        // 从对应分片表查询
    }
}

2. 中间件实现

# ShardingSphere配置
spring:
  shardingsphere:
    datasource:
      names: ds0
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/orders
        username: root
        password: root
    rules:
      sharding:
        tables:
          orders:
            actual-data-nodes: ds0.orders_$->{0..1}
            table-strategy:
              standard:
                sharding-column: user_id
                algorithm-name: orders_inline
        sharding-algorithms:
          orders_inline:
            type: INLINE
            props:
              algorithm-expression: orders_$->{user_id % 2}

最佳实践

1. 分片键选择

  • 选择业务主键
  • 避免跨分片查询
  • 考虑数据分布
  • 便于扩展

2. 分片数量

  • 考虑数据量
  • 考虑并发量
  • 考虑扩展性
  • 考虑维护成本

3. 查询优化

  • 避免跨分片查询
  • 使用分片键查询
  • 合理使用索引
  • 控制查询范围

注意事项

  1. 事务处理

    • 分布式事务
    • 跨分片事务
    • 事务一致性
    • 性能影响
  2. 跨分片查询

    • 查询性能
    • 结果合并
    • 排序分页
    • 数据一致性
  3. 分片扩展

    • 数据迁移
    • 路由调整
    • 服务升级
    • 监控告警
  4. 运维管理

    • 监控告警
    • 性能分析
    • 容量规划
    • 故障处理