1. 什么是分库分表
MySQL 分库分表是指将一张表的数据分散到多个库或多个表中,从而减轻单个数据库或表的压力,达到水平扩展的目的。
2. 分库分表的优缺点
优点
- 提高系统的可用性和稳定性
- 提高系统的性能和吞吐量
- 扩展能力强,可根据业务需求随时扩展
缺点
- 数据一致性难以保证
- 开发和维护成本高
- 对 SQL 语句的访问进行限制
3. 分库分表的实现过程
1. 分库分表的策略
分库分表的策略通常有以下几种:
- 水平分表:按照某个字段的值将表拆分成多个表,每个表存储某个范围内的数据。
- 垂直分表:将一个表的列按照业务逻辑分拆到多个表中,每个表只存储某些列。
- 水平分库:按照某个字段的值将数据分散到多个数据库中,每个库存储某个范围内的数据。
- 垂直分库:将一个数据库中的表按照业务逻辑分拆到多个数据库中,每个库只存储某些表。
2. 分库分表的实现
2.1. 水平分表
水平分表的实现通常需要以下步骤:
- 设计分表策略,选择分表键,确定分表规则。
- 修改应用程序代码,根据分表规则将数据插入到正确的表中。
- 修改查询语句,根据分表规则查询正确的表。
以按照用户 ID 分表为例,假设用户 ID 的取值范围为 1~10000,我们将用户 ID 取模,将数据分散到 10 张表中,每张表存储 1000 个用户的数据。具体实现代码如下:
public class UserDAO { private static final int TABLE_COUNT = 10; private static final String TABLE_NAME_PREFIX = "user_"; public void addUser(User user) { int tableIndex = user.getId() % TABLE_COUNT; String tableName = TABLE_NAME_PREFIX + tableIndex; // 将数据插入到正确的表中 // INSERT INTO table_name (...) VALUES (...); } public User getUserById(int id) { int tableIndex = id % TABLE_COUNT; String tableName = TABLE_NAME_PREFIX + tableIndex; // 根据分表规则查询正确的表 // SELECT * FROM table_name WHERE id = ? return null; }}
2.2. 垂直分表
垂直分表的实现通常需要以下步骤:
- 设计分表策略,选择分表键,确定分表规则。
- 创建多个表,每个表只存储某些列。
- 修改应用程序代码,根据分表规则将数据插入到正确的表中。
- 修改查询语句,根据分表规则查询正确的表。
以将用户表按照性别分拆为例,我们将用户 ID、用户名和密码存储在 user 表中,将性别和年龄存储在 user_profile 表中。具体实现代码如下:
public class UserDAO { public void addUser(User user) { // 将用户 ID、用户名和密码插入到 user 表中 // INSERT INTO user (id, name, password) VALUES (?, ?, ?); // 将性别和年龄插入到 user_profile 表中 // INSERT INTO user_profile (id, gender, age) VALUES (?, ?, ?); } public User getUserById(int id) { // 从 user 表中查询用户 ID、用户名和密码 // SELECT id, name, password FROM user WHERE id = ? // 从 user_profile 表中查询性别和年龄 // SELECT gender, age FROM user_profile WHERE id = ? return null; }}
2.3. 分库分表
分库分表的实现通常需要以下步骤:
- 设计分库分表策略,选择分库分表键,确定分库分表规则。
- 创建多个数据库,每个数据库存储某个范围内的数据。
- 在应用程序中实现数据源路由,根据分库分表规则将数据插入到正确的数据库和表中。
- 修改查询语句,根据分库分表规则查询正确的数据库和表。
以按照用户 ID 分库分表为例,假设用户 ID 的取值范围为 1~10000,我们将用户 ID 取模,将数据分散到 10 个库中,每个库中有 10 张表,每张表存储 100 个用户的数据。具体实现代码如下:
public class UserDAO { private static final int DB_COUNT = 10; private static final int TABLE_COUNT = 10; private static final String DB_NAME_PREFIX = "user_db_"; private static final String TABLE_NAME_PREFIX = "user_"; public void addUser(User user) { int dbIndex = user.getId() % DB_COUNT; int tableIndex = user.getId() / 100 % TABLE_COUNT; String dbName = DB_NAME_PREFIX + dbIndex; String tableName = TABLE_NAME_PREFIX + tableIndex; // 将数据插入到正确的数据库和表中 // INSERT INTO db_name.table_name (...) VALUES (...); } public User getUserById(int id) { int dbIndex = id % DB_COUNT; int tableIndex = id / 100 % TABLE_COUNT; String dbName = DB_NAME_PREFIX + dbIndex; String tableName = TABLE_NAME_PREFIX + tableIndex; // 根据分库分表规则查询正确的数据库和表 // SELECT * FROM db_name.table_name WHERE id = ? return null; }}
4. 总结
MySQL 分库分表是一种常用的扩展数据库性能的方法,但是需要根据业务需求选择合适的分库分表策略,并且实现过程较为复杂,需要开发和维护成本。因此,在实际应用中需要权衡利弊,慎重选择。
来源地址:https://blog.csdn.net/weixin_40648256/article/details/130508724