MySQL分區(qū)分表實(shí)現(xiàn)方法示例詳解
ShardingSphere-JDBC 通過在應(yīng)用層進(jìn)行數(shù)據(jù)分片,可以幫你輕松實(shí)現(xiàn)分區(qū)、分表和分庫,下面我用具體的配置和代碼示例來說明如何使用。
?? 特別注意:以下示例基于 ShardingSphere-JDBC 5.x 版本(Spring Boot Starter)配置。實(shí)際使用時(shí),請(qǐng)確保你的依賴版本匹配。以下示例主要展示核心配置和邏輯,實(shí)際應(yīng)用請(qǐng)參考官方文檔并根據(jù)業(yè)務(wù)調(diào)整。
為了讓你對(duì)這幾種分片方式有個(gè)快速的了解,我先用一個(gè)表格來匯總它們的主要特點(diǎn)和區(qū)別:
| 特性 | 分表 | 分庫 | 分區(qū)(按特定規(guī)則如時(shí)間) |
|---|---|---|---|
| 數(shù)據(jù)分布 | 同一庫中多表 | 不同庫中表 | 同一庫或多庫中按規(guī)則分表 |
| 性能影響 | 減輕單表壓力 | 減輕單庫壓力(可配合不同服務(wù)器) | 常用于按時(shí)間歸檔,優(yōu)化查詢和管理 |
| 配置要點(diǎn) | 指定分表算法 | 指定分庫算法 | 通常需要自定義復(fù)合分片算法 |
| 適用場景 | 單庫數(shù)據(jù)量大 | 數(shù)據(jù)量大且并發(fā)高,需分散IO | 數(shù)據(jù)有明顯冷熱特征,需定期歸檔 |
?? 分庫分表依賴
首先,確保你的 pom.xml 包含以下依賴(以 Spring Boot Starter 為例):
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.2.1</version> <!-- 請(qǐng)使用最新穩(wěn)定版本 -->
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>?? 核心概念與配置示例
1. 水平分表 (Horizontal Table Sharding)
概念:將一個(gè)邏輯表的數(shù)據(jù),按照某種規(guī)則拆分到同一個(gè)數(shù)據(jù)庫中的多個(gè)物理表中。
YAML 配置示例:
spring:
shardingsphere:
datasource:
names: ds0
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0
username: root
password: 123456
rules:
sharding:
tables:
t_order: # 邏輯表名
actual-data-nodes: ds0.t_order_$->{0..1} # 實(shí)際數(shù)據(jù)節(jié)點(diǎn),ds0庫下t_order_0, t_order_1兩張表
table-strategy:
standard:
sharding-column: order_id # 分片字段
sharding-algorithm-name: table-inline # 分表算法名稱
sharding-algorithms:
table-inline:
type: INLINE
props:
algorithm-expression: t_order_$->{order_id % 2} # 分片算法表達(dá)式,按order_id取模分到兩個(gè)表
props:
sql-show: true # 打印SQL,方便調(diào)試代碼使用:
配置好后,在代碼中操作邏輯表 t_order 即可,ShardingSphere-JDBC 會(huì)自動(dòng)路由到具體的物理表。
@Autowired
private JdbcTemplate jdbcTemplate;
public void demo() {
// 插入一條order_id為123的訂單,根據(jù) 123 % 2 = 1,會(huì)路由到 t_order_1 表
String sql = "INSERT INTO t_order (order_id, user_id, amount) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, 123L, 1000L, 200.00);
// 查詢order_id為123的訂單,同樣會(huì)路由到 t_order_1 表
List<Map<String, Object>> orders = jdbcTemplate.queryForList("SELECT * FROM t_order WHERE order_id = ?", 123L);
}2. 水平分庫 (Horizontal Database Sharding)
概念:將一個(gè)邏輯表的數(shù)據(jù),按照某種規(guī)則拆分到多個(gè)不同的數(shù)據(jù)庫中(每個(gè)數(shù)據(jù)庫可以包含該邏輯表的一個(gè)或多個(gè)物理表)。
YAML 配置示例:
spring:
shardingsphere:
datasource:
names: ds0, ds1 # 定義兩個(gè)數(shù)據(jù)源
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0
username: root
password: 123456
ds1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds1
username: root
password: 123456
rules:
sharding:
tables:
t_order:
# 實(shí)際數(shù)據(jù)節(jié)點(diǎn),兩個(gè)庫,每個(gè)庫一張表(也可每個(gè)庫多張表)
actual-data-nodes: ds$->{0..1}.t_order
database-strategy: # 分庫策略
standard:
sharding-column: user_id # 分庫字段
sharding-algorithm-name: database-inline # 分庫算法名稱
sharding-algorithms:
database-inline:
type: INLINE
props:
algorithm-expression: ds$->{user_id % 2} # 按user_id取模分庫
props:
sql-show: true代碼使用:
操作邏輯表 t_order,ShardingSphere-JDBC 根據(jù) user_id 自動(dòng)路由到對(duì)應(yīng)的數(shù)據(jù)庫。
@Autowired
private JdbcTemplate jdbcTemplate;
public void demo() {
// 插入一條user_id為1001的訂單,根據(jù) 1001 % 2 = 1,會(huì)路由到 ds1 庫的 t_order 表
String sql = "INSERT INTO t_order (order_id, user_id, amount) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, 456L, 1001L, 300.00);
// 查詢user_id為1001的訂單,同樣會(huì)路由到 ds1 庫
List<Map<String, Object>> orders = jdbcTemplate.queryForList("SELECT * FROM t_order WHERE user_id = ?", 1001L);
}3. 分區(qū)(自定義復(fù)合分片策略)
概念:這里的"分區(qū)"可以理解為更復(fù)雜的分片策略,例如按時(shí)間范圍(如月份)分表,可能同時(shí)結(jié)合分庫。這通常需要自定義分片算法。
場景:訂單表按月度分表,如 t_order_202410, t_order_202411。
YAML 配置示例:
spring:
shardingsphere:
datasource:
names: ds0
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0
username: root
password: 123456
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds0.t_order_$->{202410..202412} # 假設(shè)配置未來幾個(gè)月的表
table-strategy:
standard:
sharding-column: create_time # 分片字段為創(chuàng)建時(shí)間
sharding-algorithm-name: table-time-month # 使用自定義的時(shí)間按月分表算法
sharding-algorithms:
table-time-month:
type: CLASS_BASED # 使用自定義算法
props:
strategy: standard
algorithmClassName: com.yourpackage.algorithm.TimeMonthShardingAlgorithm # 自定義算法類
props:
sql-show: true自定義分片算法實(shí)現(xiàn):
你需要實(shí)現(xiàn) StandardShardingAlgorithm 接口。
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
public class TimeMonthShardingAlgorithm implements StandardShardingAlgorithm<LocalDateTime> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<LocalDateTime> shardingValue) {
// 處理精確分片,如 =, IN
String logicTableName = shardingValue.getLogicTableName();
LocalDateTime createTime = shardingValue.getValue();
String actualTableSuffix = formatter.format(createTime); // 根據(jù)時(shí)間生成表后綴,如202410
String actualTableName = logicTableName + "_" + actualTableSuffix; // 拼接實(shí)際表名,如t_order_202410
// 檢查計(jì)算出的表是否存在配置中
for (String each : availableTargetNames) {
if (each.equals(actualTableName)) {
return actualTableName;
}
}
throw new IllegalArgumentException("No actual table found for: " + actualTableName);
}
@Override
public Properties getProps() {
return new Properties();
}
@Override
public void init(Properties properties) {
// 初始化操作,如果需要
}
// 注意:ShardingSphere 5.x 及以上版本,可能需要實(shí)現(xiàn)其他方法,如 `getType`。請(qǐng)根據(jù)實(shí)際版本調(diào)整。
}代碼使用:
操作邏輯表 t_order,ShardingSphere-JDBC 根據(jù) create_time 自動(dòng)路由到對(duì)應(yīng)月份的表。
@Autowired
private JdbcTemplate jdbcTemplate;
public void demo() {
// 插入一條創(chuàng)建時(shí)間為當(dāng)前的訂單,會(huì)路由到對(duì)應(yīng)月份的表,如 t_order_202410
String sql = "INSERT INTO t_order (order_id, user_id, amount, create_time) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(sql, 789L, 1002L, 400.00, LocalDateTime.now());
// 查詢特定時(shí)間范圍的訂單,自定義算法中的doSharding方法會(huì)被調(diào)用
List<Map<String, Object>> orders = jdbcTemplate.queryForList("SELECT * FROM t_order WHERE create_time BETWEEN ? AND ?",
LocalDateTime.of(2024, 10, 1, 0, 0),
LocalDateTime.of(2024, 10, 31, 23, 59));
}?? 重要注意事項(xiàng)
- 確保物理表和庫存在:ShardingSphere-JDBC 不會(huì)自動(dòng)創(chuàng)建配置中涉及的物理表和數(shù)據(jù)庫,你需要在數(shù)據(jù)庫中手動(dòng)創(chuàng)建好。
- 選擇合適的分片鍵:分片鍵的選擇至關(guān)重要,應(yīng)盡量選擇數(shù)據(jù)分布均勻、業(yè)務(wù)查詢常用的字段。一旦確定,修改分片規(guī)則會(huì)非常困難。
- 避免跨庫/表關(guān)聯(lián)查詢:復(fù)雜的關(guān)聯(lián)查詢(尤其是跨庫的JOIN)在分片環(huán)境中性能很差,甚至不被支持。設(shè)計(jì)時(shí)應(yīng)盡量減少此類操作,或考慮使用綁定表。
- 分布式主鍵:在分片環(huán)境中,數(shù)據(jù)庫自增主鍵不再適用,建議使用 ShardingSphere 提供的分布式序列算法(如雪花算法 Snowflake)。
- SQL 限制:ShardingSphere-JDBC 對(duì)某些復(fù)雜 SQL(如子查詢、函數(shù)的使用)支持有限,使用時(shí)需參考官方文檔的支持列表。
?? 總結(jié)
總的來說,ShardingSphere-JDBC 通過靈活的配置,讓你能以對(duì)業(yè)務(wù)代碼低侵入的方式實(shí)現(xiàn)分片。關(guān)鍵在于理解分片概念,并根據(jù)業(yè)務(wù)特點(diǎn)設(shè)計(jì)合理的分片策略。
希望這些示例能幫助你理解和使用 ShardingSphere-JDBC。如果你能分享更多具體的業(yè)務(wù)場景,比如數(shù)據(jù)量、增長速度和常見的查詢模式,我可以給出更貼合的建議。
到此這篇關(guān)于MySQL分區(qū)分表實(shí)現(xiàn)方法詳解的文章就介紹到這了,更多相關(guān)mysql分區(qū)分表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中按月統(tǒng)計(jì)并逐月累加統(tǒng)計(jì)值的幾種實(shí)現(xiàn)寫法
有時(shí)候,我們可能有這樣的場景,需要將銷量按月統(tǒng)計(jì),并且按月逐月累加,本文就來介紹一下MySQL中按月統(tǒng)計(jì)并逐月累加統(tǒng)計(jì)值的幾種實(shí)現(xiàn)寫法,感興趣的可以了解一下2023-10-10
MySQL中count(*)、count(1)和count(字段名)的區(qū)別及說明
這篇文章主要介紹了MySQL中count(*)、count(1)和count(字段名)的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
優(yōu)化InnoDB表BLOB,TEXT列的存儲(chǔ)效率
今天小編就為大家分享一篇關(guān)于優(yōu)化InnoDB表BLOB,TEXT列的存儲(chǔ)效率,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
MySQL統(tǒng)計(jì)時(shí)間差的平均值方式
這篇文章主要介紹了MySQL統(tǒng)計(jì)時(shí)間差的平均值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
基于Redo Log和Undo Log的MySQL崩潰恢復(fù)解析
這篇文章主要介紹了基于Redo Log和Undo Log的MySQL崩潰恢復(fù)流程,點(diǎn)進(jìn)來的小伙伴不要錯(cuò)過奧2021-08-08
MySQL中SHOW DATABASES語句查看或顯示數(shù)據(jù)庫
在MySQL中,可使用SHOW DATABASES語句來查看或顯示當(dāng)前用戶權(quán)限范圍以內(nèi)的數(shù)據(jù)庫,下面就來介紹一下如何使用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02

