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. 查询优化
- 避免跨分片查询
- 使用分片键查询
- 合理使用索引
- 控制查询范围
注意事项
-
事务处理
- 分布式事务
- 跨分片事务
- 事务一致性
- 性能影响
-
跨分片查询
- 查询性能
- 结果合并
- 排序分页
- 数据一致性
-
分片扩展
- 数据迁移
- 路由调整
- 服务升级
- 监控告警
-
运维管理
- 监控告警
- 性能分析
- 容量规划
- 故障处理