Sharding-jdbc 假如全表有20年的数据,按年分表,只需要查最近五年的,该怎么处理
当 Sharding-JDBC 已按年分表(全表20年数据,如 order_2004~ order_2023),且只需查询最近五年数据时,核心目标是让 Sharding-JDBC 自动路由到目标年份的分片表,避免全表扫描或无关分片访问。以下是针对性的落地方案:
一、前提:确保分片规则正确配置
首先,需保证 Sharding-JDBC 的分片策略基于时间字段(如 create_time)按年分表。以 Spring Boot 配置为例:
spring:shardingsphere:# 数据源配置(略)sharding:tables:order: # 逻辑表名actual-data-nodes: ds${0..1}.order_${year} # 物理表:ds0/order_2004、ds1/order_2005...ds1/order_2023table-strategy:inline:sharding-column: create_time # 分片键(必须是时间类型)algorithm-expression: order_${YEAR(create_time)} # 分表算法:按create_time的年份取模(实际是提取年份作为表后缀)key-generate-strategy: # 主键生成(可选)column: idkey-generator-name: snowflake二、核心方案:用「时间范围条件」触发自动路由
Sharding-JDBC 的分片算法会解析查询条件中的分片键范围,自动计算需要访问的年份分片表。只需在查询 SQL 中包含时间范围条件,即可精准定位最近五年的分片。
1. 示例 SQL:查询最近五年的订单
假设当前时间是 2024-10-01,需查询 create_time在最近五年(2019-10-01 至 2024-10-01)内的数据:
SELECT * FROM order
WHERE create_time >= DATE_SUB(CURRENT_DATE(), INTERVAL 5 YEAR);Sharding-JDBC 的路由逻辑:
- 解析
create_time >= '2019-10-01'条件; - 计算该时间范围覆盖的年份分片:2019(部分数据)、2020、2021、2022、2023、2024(全部数据);
- 仅路由到
order_2019、order_2020、order_2021、order_2022、order_2023、order_2024这些物理表,不会查询 2018 及更早的表。
2. 关键优化:为时间字段加索引
即使路由到了目标分片表,若 create_time无索引,仍会全表扫描。因此必须为分片键(create_time)添加索引:
ALTER TABLE order ADD INDEX idx_create_time (create_time);三、特殊情况:查询条件不含分片键怎么办?
若因业务需求,查询无法包含 create_time(如按用户 ID 查询,但需限制最近五年),可使用 HintManager 强制指定分片表:
import org.apache.shardingsphere.api.hint.HintManager;// 手动指定需要查询的年份分片(如2019~2024)
List<String> targetTables = Arrays.asList("order_2019", "order_2020", "order_2021", "order_2022", "order_2023", "order_2024");try (HintManager hintManager = HintManager.getInstance()) {// 添加表级别的分片值(告诉Sharding-JDBC只查这些表)targetTables.forEach(tableName -> hintManager.addTableShardingValue("order", tableName));// 执行查询(无需SQL带时间条件)List<Order> orders = orderMapper.selectByUserId(123);
}注意:需自行计算最近五年对应的表名(如根据当前年份倒推),适用于查询条件与分片键无关的场景。
四、验证:确保路由正确
可通过开启 ShardingSphere SQL 日志验证是否仅访问目标分片:
spring:shardingsphere:props:sql-show: true # 开启SQL日志日志中会显示类似内容,证明仅路由到目标表:
[ShardingSphere-Proxy] SQL: SELECT * FROM order_2019 WHERE create_time >= ?
[ShardingSphere-Proxy] SQL: SELECT * FROM order_2020 WHERE create_time >= ?
...五、进一步优化:数据归档
若最近五年的数据仍是海量(如单表过亿),可结合冷热数据分离:
- 归档旧数据:将五年前的数据迁移到归档库(如单独的 MySQL 实例或 HBase);
- 逻辑删除:主库中保留历史数据,但标记为
is_deleted=1; - 查询优化:主库仅查最近五年的非删除数据,归档数据按需查询。
这样主库的单表数据量大幅减少,查询性能进一步提升。
总结:最佳实践
- 正确配置分片规则:基于时间字段按年分表,确保分片算法能解析时间范围;
- 查询带时间条件:用
create_time >= 五年前日期触发自动路由; - 加索引:为
create_time加索引,避免分片内全表扫描; - 必要时强制路由:查询无分片键时用 HintManager 指定表;
- 数据归档:长期优化,减少主库数据量。
通过以上方案,Sharding-JDBC 会精准定位最近五年的分片表,避免无效扫描,保证查询效率。
