一蕾殴、序言
在實際業(yè)務中,單表數(shù)據(jù)增長較快黄伊,很容易達到數(shù)據(jù)瓶頸泪酱,比如單表百萬級別數(shù)據(jù)量。當數(shù)據(jù)量繼續(xù)增長時还最,數(shù)據(jù)的查詢性能
即使有索引的幫助下也不盡如意墓阀,這時可以引入數(shù)據(jù)分庫分表
技術(shù)。
本文將基于SpringBoot
+MybatisPlus
+Sharding-JDBC
+Mysql
實現(xiàn)企業(yè)級分庫分表憋活。
1岂津、組件及版本選擇
SpringBoot 2.6.x | MybatisPlus 3.5.0 | Sharding-JDBC 4.1.1 | Mysql 5.7.35 |
2虱黄、預期目標
- 使用上述組件實現(xiàn)分庫分表悦即,簡化起見只討論分表技術(shù)
- 完成分表后的邏輯表與物理表間的增刪查改
- 引入邏輯刪除和使用MybatisPlus內(nèi)置分頁技術(shù)
完整項目源碼訪問地址。
二橱乱、代碼實現(xiàn)
為了簡化分表復雜性辜梳,專注于分表整體實現(xiàn),簡化分表邏輯:按照UserId
的奇偶屬性分別進行分表泳叠。以訂單表這一典型場景為例作瞄,一般來說有關(guān)訂單表,通常具有如下共性行為:
- 創(chuàng)建訂單記錄
- 查詢XX用戶的訂單列表
- 查詢XX用戶的訂單列表(分頁)
- 查詢XX訂單詳情
- 修改訂單狀態(tài)
- 刪除訂單(邏輯刪除)
接下來通過代碼實現(xiàn)上述目標危纫。
(一)素材準備
1宗挥、實體類
@Data
@TableName("bu_order")
public class Order {
@TableId
private Long orderId;
private Integer orderType;
private Long userId;
private Double amount;
private Integer orderStatus;
@TableLogic
@JsonIgnore
private Boolean deleted;
}
2、Mapper類
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}
3种蝶、全局配置文件
spring:
config:
use-legacy-processing: true
shardingsphere:
datasource:
ds1:
driver-class-name: com.Mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/sharding-jdbc2?serverTimezone=UTC
username: root
password: 123456
names: ds1
props:
SQL:
show: true
sharding:
tables:
bu_order:
actual-data-nodes: ds1.bu_order_$->{0..1}
key-generator:
column: order_id
type: SNOWFLAKE
table-strategy:
inline:
algorithm-expression: bu_order_${user_id%2}
sharding-column: user_id
(二)增刪查改
1契耿、保存數(shù)據(jù)
由于依據(jù)主鍵的奇偶屬性對原表分表,分表后每張表的數(shù)據(jù)量是分表前的二分之一螃征。根據(jù)需要也可以自定義分表數(shù)量(比如10張)搪桂,新分表后的數(shù)據(jù)量是不分表前的十分之一。
@Test
public void addOrders() {
for (long i = 1; i <= 10; i++) {
Order order = new Order();
order.setOrderId(i);
order.setOrderType(RandomUtil.randomEle(Arrays.asList(1, 2)));
order.setUserId(RandomUtil.randomEle(Arrays.asList(101L, 102L, 103L)));
order.setAmount(1000.0 * i);
orderMapper.insert(order);
}
}
2盯滚、查詢列表數(shù)據(jù)
查詢指定用戶的訂單列表踢械。
@GetMapping("/list")
public AjaxResult list(Order order) {
LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery(order);
return AjaxResult.success(orderMapper.selectList(wrapper));
}
3酗电、分頁查詢數(shù)據(jù)
分頁查詢指定用戶的訂單列表
@GetMapping("/page")
public AjaxResult page(Page<Order> page, Order order) {
return AjaxResult.success(orderMapper.selectPage(page, Wrappers.lambdaQuery(order)));
}
4、查詢詳情
通過訂單ID查詢訂單詳情内列。
@GetMapping("/detail/{orderId}")
public AjaxResult detail(@PathVariable Long orderId) {
return AjaxResult.success(orderMapper.selectById(orderId));
}
5撵术、刪除數(shù)據(jù)
通過訂單ID刪除訂單(邏輯刪除)
@DeleteMapping("/delete/{orderId}")
public AjaxResult delete(@PathVariable Long orderId) {
return AjaxResult.success(orderMapper.deleteById(orderId));
}
6、修改數(shù)據(jù)
修改數(shù)據(jù)一般涉及部分列德绿,比如修改訂單表的訂單狀態(tài)等荷荤。
@PutMapping("/edit")
public AjaxResult edit(@RequestBody Order order) {
return AjaxResult.success(orderMapper.updateById(order));
}
三、理論分析
1移稳、選擇分片列
選擇分片列是經(jīng)過精心對比后確定的蕴纳,對于訂單類場景,需要頻繁以用戶ID為查詢條件篩選數(shù)據(jù)个粱,因此將同一個用戶的訂單數(shù)據(jù)存放在一起有利于提高查詢效率古毛。
2、擴容
當分表后的表數(shù)據(jù)快速增長都许,可以預見即將達到瓶頸時稻薇,需要對分表進行擴容,擴容以2倍
的速率進行胶征,擴容期間需要遷移數(shù)據(jù)塞椎,工作量相對可控。
喜歡本文點個??贊??支持一下睛低,如有需要案狠,可通過微信
dream4s
與我聯(lián)系。相關(guān)源碼在GitHub钱雷,視頻講解在B站骂铁,本文收藏在博客天地。