当前位置: 首页 > news >正文

Sharding-jdbc 有20年数据,每年分一张表,查询指定日期近两年数据,跨年查询如何处理

在 Sharding-JDBC 中处理每年一张表查询指定日期近两年跨年数据的场景,核心是通过自定义范围分片算法(RangeShardingAlgorithm)精准定位目标年份的表,并自动合并结果。以下是具体实现方案、关键细节和验证步骤:

一、场景再明确

  • 表结构:订单表按年分表,命名为 t_order_YYYY(如 t_order_2022t_order_2023t_order_2024t_order_2042,共20张表)。
  • 分片键:订单创建时间 create_timeDATETIME 类型)。
  • 查询需求:给定指定日期(如 2024-06-01),查询该日期前推两年的数据(即 2022-06-01 ~ 2024-06-01),涉及 202220232024 三年表。

二、核心解决方案:RangeShardingAlgorithm 处理时间范围

Sharding-JDBC 的范围分片算法RangeShardingAlgorithm)用于处理时间区间查询,其作用是:
接收 SQL 中的 create_time 范围条件,计算对应的年份区间,返回需要查询的分表集合(如 t_order_2022t_order_2023t_order_2024)。

三、具体实现步骤

1. 自定义 RangeShardingAlgorithm

实现算法逻辑:从分片值中提取时间范围,计算起始/结束年份,筛选对应的表名。

import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;import java.util.*;
import java.util.regex.Pattern;/*** 按年分表的 RangeShardingAlgorithm(处理指定日期近两年查询)* 示例:查询 create_time ∈ [start, end],返回对应年份的表*/
public class OrderYearRangeShardingAlgorithm implements RangeShardingAlgorithm<Date> {// 表名前缀(如 "t_order_")private static final String TABLE_PREFIX = "t_order_";// 年份正则(从表名中提取年份)private static final Pattern YEAR_PATTERN = Pattern.compile(TABLE_PREFIX + "(\\d{4})");@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames,  // 所有可选分表(如 t_order_2022~t_order_2042)RangeShardingValue<Date> shardingValue    // 分片值(包含 create_time 的范围)) {// 1. 提取查询的时间范围(start/end)Date startTime = shardingValue.getValueRange().lowerEndpoint();Date endTime = shardingValue.getValueRange().upperEndpoint();// 2. 计算起始年份和结束年份int startYear = getYearFromDateTime(startTime);int endYear = getYearFromDateTime(endTime);// 3. 筛选符合条件的分表(年份在 [startYear, endYear] 之间)Set<String> result = new HashSet<>();for (String tableName : availableTargetNames) {// 从表名中提取年份(如 t_order_2023 → 2023)Integer tableYear = extractYearFromTableName(tableName);if (tableYear != null && tableYear >= startYear && tableYear <= endYear) {result.add(tableName);}}return result;}/*** 从 Date 中提取年份*/private int getYearFromDateTime(Date date) {Calendar cal = Calendar.getInstance();cal.setTime(date);return cal.get(Calendar.YEAR);}/*** 从表名中提取年份(如 t_order_2023 → 2023)*/private Integer extractYearFromTableName(String tableName) {java.util.regex.Matcher matcher = YEAR_PATTERN.matcher(tableName);if (matcher.matches()) {return Integer.parseInt(matcher.group(1));}return null; // 非分表,忽略}
}
2. 配置 Sharding-JDBC(Spring Boot YAML)

绑定表名规则和自定义算法:

spring:shardingsphere:datasource:names: ds  # 单数据源(所有分表在同一库,也可分散在不同库)ds:url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTCusername: rootpassword: 123456rules:sharding:tables:t_order:# 实际分表节点:所有年份的表(2022~2042)actual-data-nodes: ds.t_order_${2022..2042}# 分库策略(无分库,所有表在同一库)database-strategy:none:# 分表策略:按 create_time 的年份分表table-strategy:standard:sharding-column: create_time# 绑定自定义的 RangeShardingAlgorithmsharding-algorithm-name: order_year_range# 自定义分片算法sharding-algorithms:order_year_range:type: CLASS_BASEDprops:strategy: STANDARDalgorithm-class-name: com.example.config.OrderYearRangeShardingAlgorithm  # 自定义算法的全限定类名

四、查询验证:SQL 路由与结果合并

1. 示例 SQL(查询指定日期近两年数据)

假设指定日期为 2024-06-01,查询 create_time2022-06-01 ~ 2024-06-01 之间的订单:

SELECT * FROM t_order 
WHERE create_time BETWEEN '2022-06-01 00:00:00' AND '2024-06-01 23:59:59';
2. 路由逻辑拆解
  1. 解析分片键:Sharding-JDBC 提取 SQL 中的 create_time 范围条件(2022-06-012024-06-01)。
  2. 调用 RangeShardingAlgorithm
    • 计算起始年份 2022,结束年份 2024
    • availableTargetNames(所有分表)中筛选出 t_order_2022t_order_2023t_order_2024
  3. 执行分片查询:向这三张表分别发送 SQL,查询对应年份的数据。
  4. 合并结果:Sharding-JDBC 自动将三张表的查询结果合并,返回完整的跨年数据集。

五、关键注意事项

1. SQL 必须包含分片键条件

跨年查询必须包含 create_time 的范围条件,否则 Sharding-JDBC 无法路由,会触发全表扫描(查询所有20张表)。
错误示例SELECT * FROM t_order(无分片键,全表扫描)。
正确示例SELECT * FROM t_order WHERE create_time >= '2022-06-01'(包含分片键)。

2. 指定日期的处理逻辑

若指定日期是 D,近两年的时间范围通常是 D - 2年D(如 2024-06-012022-06-01 ~ 2024-06-01)。
算法中需准确计算起始年份和结束年份,避免遗漏或多查表。

3. 性能优化
  • 索引优化:在 create_time 字段上建立索引,加速范围查询(尤其是跨多张表时)。
  • 分表数量控制:若20年数据导致分表过多(如20张),可考虑按月分表(更细粒度,但需调整算法)。
  • 归档历史数据:将旧数据迁移至归档库,减少当前库的分表数量。
4. 结果排序与分页
  • 全局排序:若 SQL 包含 ORDER BY create_time,Sharding-JDBC 会合并分片结果后二次排序,无需额外处理。
  • 分页LIMIT/OFFSET 会由 Sharding-JDBC 合并分片结果后计算,确保正确性。

六、验证路由正确性

开启 Sharding-JDBC 的 SQL 日志,查看实际路由的表:

spring:shardingsphere:props:sql-show: true  # 打印 SQL 路由日志

日志示例:

DEBUG [main] o.a.s.r.r.RouteUnit - Logic SQL: SELECT * FROM t_order WHERE create_time BETWEEN ? AND ?
DEBUG [main] o.a.s.r.r.RouteUnit - Actual SQL: ds ::: SELECT * FROM t_order_2022 WHERE create_time BETWEEN ? AND ?
DEBUG [main] o.a.s.r.r.RouteUnit - Actual SQL: ds ::: SELECT * FROM t_order_2023 WHERE create_time BETWEEN ? AND ?
DEBUG [main] o.a.s.r.r.RouteUnit - Actual SQL: ds ::: SELECT * FROM t_order_2024 WHERE create_time BETWEEN ? AND ?

七、总结

Sharding-JDBC 处理每年一张表的跨年查询的核心是:

  1. 自定义 RangeShardingAlgorithm:处理时间范围,返回对应年份的表。
  2. SQL 包含分片键:确保路由到正确的表。
  3. 自动合并结果:Sharding-JDBC 处理跨表结果的合并与排序。

通过以上配置,可高效支持“指定日期近两年”的跨年查询,同时兼容长期数据扩展(新增年份表只需更新 actual-data-nodes 或算法逻辑)。

http://www.dtcms.com/a/615491.html

相关文章:

  • php ajax网站开发典型实例 pdf网络架构方案规划设计和实施
  • 平台网站建设方案模板开通网站需要多少钱
  • 网站制作 太原合肥做网站好的公司哪家好
  • 东莞网站设计与网站制作西安有什么好玩的游乐园
  • 《PyTorch深度学习建模与应用(参考用书)》(零)——深度学习综述
  • 深耕C语言动态内存:realloc实战与数组求和综合练习
  • 网站建设 会议纪要网店运营的基本流程
  • 前端微前端应用加载策略,预加载与懒加载
  • 杭州滨江网站制作东莞网络公司招聘信息
  • 嘉兴网站建设低价推荐网站建设公司效果
  • HTTP , Websocket 和SSE三者的区别
  • 监控做斗鱼直播网站三水网站制作
  • 做百度网站需要多少钱网站维护知识
  • 掌握C语言:全局变量的完整生命周期
  • 网站架构设计师月薪多少缪斯设计
  • 网站建设用什么网站描述更改
  • 个人网站成功案例淘宝客网站备案号
  • 建站排行榜兰州网站seo
  • 怎么建设一个网站并顺利打开浏览信息网站建设
  • 易语言模块反编译工具 | 深入探讨易语言反编译技术及应用
  • 营销型网站制作建设怎样建设一个能上传数据的网站
  • 江门网站建设价格怎么在手机上自己开发软件
  • 宁波微信公众号开发公司seo网站首页优化排名怎么做
  • 运城网站建设哪个好关键词网站推广
  • 小白自己做网站网站建设的市场分析
  • 集合练习1
  • 苍南做网站哪里找深圳创业项目
  • 网站系统建设的主要意义离型剂技术支持东莞网站建设
  • 如何用rp做网站基于jsp的网上购物系统
  • 江门网站设计价格做贺卡网站