【shardingsphere-jdbc】分表实践

一、背景

博主的一个线上IT项目,由于Oracle单表数据量超过了10亿条,出现线上查询超时,无法正确响应用户请求的问题。因此,计划在现有代码工程 中整合shardingsphere-jdbc组件,对该表进行分表处理,优化用户查询速度。

现有代码工程的技术框架为:SpringBoot+MybatisPlus+Oracle

二、注意事项

  1. 现有代码工程整合shardingsphere-jdbc组件后,发现工程里的所有Mapper统一使用shardingsphere-jdbc,暂未研究指定Mapper使用shardingsphere-jdbc的方式。博主的IT项目功能模块较少,因此整合后对IT项目功能进行了全量回归;
  2. 由于设计按照年份进行分表,但配置项中actual-data-nodes内容是写死,需要在新增分表后修改该配置项内容,或者研究动态修改该配置项的方法。

三、版本号

shardingsphere-jdbc不同版本之间配置方式有差异,博主花费了不少时间编辑配置项的内容,最后使用的shardingsphere-jdbc版本信息如下:

xml 复制代码
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.0</version>
</dependency>

四、配置文件

ini 复制代码
spring.shardingsphere.mode.type=Standalone
spring.shardingsphere.props.sql-show=true
spring.shardingsphere.datasource.names=shard-test
spring.shardingsphere.datasource.shard-test.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.shard-test.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.shardingsphere.datasource.shard-test.jdbc-url=jdbc:oracle:thin:@10.101.30.196:1528/zcgj
spring.shardingsphere.datasource.shard-test.username=zcgj
spring.shardingsphere.datasource.shard-test.password=zcgj@2023poiuy

spring.shardingsphere.rules.sharding.tables.SHARD.table-strategy.standard.sharding-column=create_year #自定义分表字段
spring.shardingsphere.rules.sharding.tables.SHARD.actual-data-nodes=shard-test.SHARD_$->{2020..2025} #自定义表名区间
spring.shardingsphere.rules.sharding.tables.SHARD.table-strategy.standard.sharding-algorithm-name=create-year #自定义分表逻辑命名
spring.shardingsphere.rules.sharding.sharding-algorithms.create-year.type=inline #分表逻辑类型枚举值
spring.shardingsphere.rules.sharding.sharding-algorithms.create-year.props.algorithm-expression=SHARD_${create_year} #分表逻辑

五、分表结果验证

接口验证用例如下,结论在以下注释中:

scss 复制代码
@Test
public void test() {
    // 数据可以按照逻辑,插入到不同create-year的表中
    List<ShardEntity> list = new LinkedList<>();
    for (int k = 2020; k <= 2025; k++) {
        for (int i = 0; i < 500; i++) {
            for (int j = 0; j < 1000; j++) {
                ShardEntity shardEntity = new ShardEntity();
                shardEntity.setId(UUID.randomUUID().toString().replace("-",""));
                shardEntity.setCreateTime(new Date());
                shardEntity.setCreateYear(String.valueOf(k));
                list.add(shardEntity);
            }
            this.shardService.saveBatch(list);
            list.clear();
        }
    }

    // 列表查询数据范围涉及多张分表时,list接口返回的是各个分表的汇总数据,如下返回了20条数据,而非10条
    LambdaQueryWrapper<ShardEntity> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.in(ShardEntity::getCreateYear, new String[]{"2024", "2025"})
            .orderByDesc(ShardEntity::getCreateTime) // 按时间降序排序
            .apply("ROWNUM <= 10"); // 限制只返回第一条记录
    List<ShardEntity> shards = this.shardService.list(queryWrapper);
    log.info("shards=[{}]", shards);

    // 分页查询数据范围涉及多张分表时,page接口返回条数为10条,优先返回SHARD_2024表中的内容
    queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.in(ShardEntity::getCreateYear, new String[]{"2024", "2025"})
            .orderByDesc(ShardEntity::getCreateTime); // 按时间降序排序
    Page page = new Page();
    page.setCurrent(1);
    page.setSize(10);
    Page<ShardEntity> shardEntityPage = this.shardService.page(page, queryWrapper);
    log.info("shardEntityPage=[{}]", shardEntityPage);
}

附:建表语句

less 复制代码
CREATE TABLE "SHARD_2020" 
   (	"ID" VARCHAR2(32), 
	"REQ_ID" VARCHAR2(64), 
	"REQ_SOURCE" VARCHAR2(32), 
	"ERRCODE" NUMBER(16,0), 
	"ERRMSG" VARCHAR2(1024), 
	"CREATE_TIME" DATE DEFAULT SYSDATE, 
	"UPDATE_TIME" DATE DEFAULT SYSDATE, 
	"CREATE_USER" VARCHAR2(16), 
	"UPDATE_USER" VARCHAR2(16), 
	"CREATE_YEAR" VARCHAR2(8), 
	PRIMARY KEY ("ID")
  )
相关推荐
xxy.c3 小时前
基于IMX6ULL芯片--I2C总线简单应用
数据库·mongodb
cookqq3 小时前
MongoDB源码分析慢日志:从配置到实现的完整解析
数据库·mongodb·nosql·慢日志
道可到3 小时前
淘宝面试原题 Java 面试通关笔记 02|从编译到运行——Java 背后的计算模型(面试可复述版)
java·后端·面试
8K超高清3 小时前
汇世界迎全运 广州国际社区运动嘉年华举行,BOSMA博冠现场展示并分享与科技全运的故事
运维·服务器·网络·数据库·人工智能·科技
DKPT3 小时前
JVM如何管理直接内存?
java·笔记·学习
SimonKing3 小时前
GitHub 标星 370k!免费编程资源大合集,从此自学不花一分钱
java·后端·程序员
come112343 小时前
深入Spring Boot生态中最核心部分 数据库交互spring-boot-starter-data-jpa和Hibernate (指南五)
数据库·spring boot·hibernate
kfepiza3 小时前
Java的任务调度框架之Quartz 笔记250930
java·java ee
自由的疯3 小时前
Java(32位)基于JNative的DLL函数调用方法
java·后端·架构