目录前言一、为什么需要 ShardingSphere二、什么是 ShardingSphere三、ShardingSphere 解决了什么问题四、ShardingSphere 的核心概念1. 逻辑表2. 真实表3. 分片键4. 分片算法五、Spring Boot 集成 ShardingSphere1. 引入依赖2. 配置数据源3. 是否还需要 spring.datasource六、配置真实表七、按月份分表1. 配置分片策略2. sharding-column 是什么3. 必须有 create_time 字段吗八、配置时间分片算法1. datetime-pattern2. datetime-lower3. datetime-upper4. sharding-suffix-pattern5. datetime-interval-unit九、MyBatis 和 MyBatis Plus 如何使用1. Mapper 不需要修改2. XML 不需要修改3. ShardingSphere 自动改写 SQL十、查询如何路由1. 精准路由2. 范围路由3. 全路由十一、每个 SQL 都必须带分片键吗十二、ShardingSphere 会自动创建表吗十三、如何自动创建分表1. 推荐方案2. 定时任务创建3. Flyway 或 Liquibase十四、生产环境如何设计分表1. 单纯按月份分表2. 按用户 Hash 分表3. 时间 Hash十五、ShardingSphere 的优缺点优点缺点十六、总结前言随着业务的发展订单表、支付表、交易流水表等核心业务表的数据量会不断增长。当单表数据达到数千万甚至上亿级别时查询性能、索引维护、数据备份和数据库扩容等问题都会逐渐显现。为了解决单表数据量过大的问题互联网系统通常会采用分库分表方案将数据按照一定规则拆分到多个数据库或数据表中。然而分库分表之后也会带来新的挑战例如如何确定数据应该存储到哪张表、如何跨表查询数据、如何降低业务代码的改造成本等。ShardingSphere正是为了解决这些问题而诞生的。它能够在应用层和数据库之间提供透明的分片能力让开发人员仍然像操作普通数据表一样进行开发而无需关心底层的数据路由和 SQL 改写过程。本文将结合 Spring Boot 和 MyBatis 项目从分库分表的背景开始逐步介绍 ShardingSphere 的核心概念、工作原理、项目集成方式、分片算法配置以及实际项目中的使用技巧帮助读者快速掌握 ShardingSphere 的基本使用与设计思路。shardingsphere官网shardingsphere HitHub地址一、为什么需要 ShardingSphere随着业务发展订单表、支付表、流水表的数据量会越来越大。例如有一张支付订单表CREATETABLEpay_info(idBIGINTPRIMARYKEY,order_noVARCHAR(64),user_idBIGINT,amountDECIMAL(18,2),create_timeDATETIME);如果每天产生 100 万条数据100万/天 ≈ 3000万/月 ≈ 3.6亿/年几年之后单表可能达到几十亿数据。此时会出现很多问题查询变慢索引变大备份恢复困难DDL操作耗时数据迁移困难因此需要进行分库分表最常见的方案按时间分表按用户分表按订单号分表而目前 Java 生态中最主流的分库分表框架之一就是 Apache ShardingSphere。二、什么是 ShardingSphereShardingSphere 是 Apache 顶级项目。它是一套数据库中间件生态主要功能包括分库分表读写分离分布式事务数据加密SQL 路由SQL 改写在 Spring Boot 项目中最常见的是ShardingSphere-JDBC其架构如下MyBatis ↓ ShardingSphere ↓ MySQL对于业务代码来说感知不到分表的存在三、ShardingSphere 解决了什么问题假设数据库中有以下表pay_info_202601 pay_info_202602 pay_info_202603 ...程序中仍然写select*frompay_info或者payInfoMapper.insert(payInfo);增删改查时 ShardingSphere 会自动帮你改写 SQL。例如createTime2026-05-15自动路由insertintopay_info_202605开发人员完全不需要手动判断表名。四、ShardingSphere 的核心概念1. 逻辑表程序中看到的表pay_info称为逻辑表。例如select*frompay_info2. 真实表数据库真正存在的表pay_info_202601 pay_info_202602 pay_info_202603称为真实表。3. 分片键决定数据进入哪张表的字段。例如create_time或者user_id或者order_no都可以作为分片键。4. 分片算法根据分片键计算目标表。例如2026-05-15计算得到pay_info_202605五、Spring Boot 集成 ShardingSphere1. 引入依赖dependencygroupIdorg.apache.shardingsphere/groupIdartifactIdshardingsphere-jdbc-core-spring-boot-starter/artifactId/dependency2. 配置数据源spring:shardingsphere:datasource:names:dsds:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/testusername:rootpassword:root这里的url username password就是实际数据库连接配置。3. 是否还需要 spring.datasource上面在 shardingsphere 下已经配置了数据源了是否还需要 spring.datasource 通常不需要。不要同时配置spring:datasource:和spring:shardingsphere:datasource:否则可能出现NoUniqueBeanDefinitionException因为 Spring 中会存在多个 DataSource Bean。六、配置真实表假设数据库已经存在pay_info_202601 pay_info_202602 ... pay_info_203012配置如下spring:shardingsphere:rules:sharding:tables:pay_info:actual-data-nodes:ds.pay_info_$-{202601..203012}含义逻辑表 pay_info 真实表 pay_info_202601 pay_info_202602 ... pay_info_203012七、按月份分表1. 配置分片策略table-strategy:standard:sharding-column:create_timesharding-algorithm-name:pay-info-month2. sharding-column 是什么表示根据哪个字段决定路由例如sharding-column:create_time表示根据 create_time 决定数据进入哪张表例如2026-05-20自动进入pay_info_2026053. 必须有 create_time 字段吗不一定。可以使用sharding-column:pay_time或者sharding-column:order_time只要能够表达时间即可。八、配置时间分片算法sharding-algorithms:pay-info-month:type:INTERVALprops:datetime-pattern:yyyy-MM-dd HH:mm:ssdatetime-lower:2025-01-01 00:00:00datetime-upper:2030-12-31 23:59:59sharding-suffix-pattern:yyyyMMdatetime-interval-unit:MONTHS1. datetime-pattern时间格式。yyyy-MM-dd HH:mm:ss例如2026-05-1815:20:302. datetime-lower开始时间2025-01-01 00:00:003. datetime-upper结束时间2030-12-31 23:59:594. sharding-suffix-pattern表后缀格式。例如yyyyMM生成pay_info_202605如果yyyy_MM生成pay_info_2026_055. datetime-interval-unit分片粒度。按月MONTHS生成pay_info_202605 pay_info_202606按天DAYS生成pay_info_20260501 pay_info_20260502按年YEARS生成pay_info_2025 pay_info_2026九、MyBatis 和 MyBatis Plus 如何使用1. Mapper 不需要修改例如MapperpublicinterfacePayInfoMapper{PayInfoselectById(Longid);}2. XML 不需要修改仍然写selectidselectByIdselect * from pay_info where id #{id}/select不要写pay_info_202605也不要写pay_info_202606统一写pay_info即可。3. ShardingSphere 自动改写 SQL程序select*frompay_info实际执行select*frompay_info_202605或者select*frompay_info_202605unionallselect*frompay_info_202606十、查询如何路由1. 精准路由例如select*frompay_infowherecreate_time2026-05-01andcreate_time2026-06-01只查询pay_info_202605性能最好。2. 范围路由例如select*frompay_infowherecreate_timebetween2026-05-01and2026-07-31查询pay_info_202605 pay_info_202606 pay_info_2026073. 全路由例如select*frompay_infowherestatus1没有分片键create_timeShardingSphere 无法判断目标表。于是pay_info_202601 pay_info_202602 ... pay_info_203012全部查询。这就是全路由性能极差。十一、每个 SQL 都必须带分片键吗不是必须。可以正常执行。但是不带分片键 全路由 查询所有分表因此在设计表结构时高频查询条件 最好就是分片键这样性能最高。十二、ShardingSphere 会自动创建表吗不会。ShardingSphere 负责SQL路由不负责创建表例如insertintopay_info路由到pay_info_202606如果pay_info_202606不存在。直接报错Table doesnt exist十三、如何自动创建分表1. 推荐方案提前创建未来几年表。例如pay_info_202601 ... pay_info_203012一次建好即可。2. 定时任务创建假设每月1号创建未来三个月的表1定时任务//每个月的 1 号凌晨 2 点整执行一次Scheduled(cron0 0 2 1 * ?)publicvoidcreateFutureTables(){//循环三次创建未来三个月的表for(inti1;i3;i){LocalDatemonthLocalDate.now().plusMonths(i);//检查表是否存在不存在则创建createTableIfNotExists(month);}}2模板表一般会准备一个模板表CREATETABLEpay_info_template(idBIGINTPRIMARYKEY,order_noVARCHAR(64),amountDECIMAL(18,2),create_timeDATETIME,KEYidx_create_time(create_time));(3) 使用 JdbcTemplate 创建表AutowiredprivateJdbcTemplatejdbcTemplate;privatevoidcreateTableIfNotExists(LocalDatemonth){StringtableNameString.format(pay_info_%d_%02d,month.getYear(),month.getMonthValue());StringsqlCREATE TABLE IF NOT EXISTS tableName LIKE pay_info_template;jdbcTemplate.execute(sql);}效果假设 当前是2026-05定时任务会执行CREATETABLEIFNOTEXISTSpay_info_202606LIKEpay_info_template;CREATETABLEIFNOTEXISTSpay_info_202607LIKEpay_info_templateCREATETABLEIFNOTEXISTSpay_info_202608LIKEpay_info_template最终创建了pay_info_2026_06 pay_info_2026_07 pay_info_2026_083. Flyway 或 Liquibase使用数据库版本管理工具自动创建。十四、生产环境如何设计分表1. 单纯按月份分表pay_info_202605 pay_info_202606 pay_info_202607适合按时间查询较多2. 按用户 Hash 分表pay_info_00 pay_info_01 ... pay_info_63路由userId%64适合根据用户查询较多3. 时间 Hash大型支付系统最常见。例如pay_info_202605_00 pay_info_202605_01 ... pay_info_202605_15优势控制单表大小查询效率高扩展能力强十五、ShardingSphere 的优缺点优点对业务代码侵入小MyBatis 基本不用改自动路由自动聚合结果支持读写分离支持分布式事务支持分库分表缺点配置复杂SQL 不宜过于复杂跨分片查询成本高全路由性能差分页查询需要特别注意十六、总结ShardingSphere 本质上是一个数据库中间层。对于开发人员来说仍然操作逻辑表 pay_info对于数据库来说实际访问真实表 pay_info_202605 pay_info_202606其核心思想只有一句话开发只关心逻辑表 ShardingSphere负责将SQL路由到正确的真实表。
Spring Boot + ShardingSphere 介绍
目录前言一、为什么需要 ShardingSphere二、什么是 ShardingSphere三、ShardingSphere 解决了什么问题四、ShardingSphere 的核心概念1. 逻辑表2. 真实表3. 分片键4. 分片算法五、Spring Boot 集成 ShardingSphere1. 引入依赖2. 配置数据源3. 是否还需要 spring.datasource六、配置真实表七、按月份分表1. 配置分片策略2. sharding-column 是什么3. 必须有 create_time 字段吗八、配置时间分片算法1. datetime-pattern2. datetime-lower3. datetime-upper4. sharding-suffix-pattern5. datetime-interval-unit九、MyBatis 和 MyBatis Plus 如何使用1. Mapper 不需要修改2. XML 不需要修改3. ShardingSphere 自动改写 SQL十、查询如何路由1. 精准路由2. 范围路由3. 全路由十一、每个 SQL 都必须带分片键吗十二、ShardingSphere 会自动创建表吗十三、如何自动创建分表1. 推荐方案2. 定时任务创建3. Flyway 或 Liquibase十四、生产环境如何设计分表1. 单纯按月份分表2. 按用户 Hash 分表3. 时间 Hash十五、ShardingSphere 的优缺点优点缺点十六、总结前言随着业务的发展订单表、支付表、交易流水表等核心业务表的数据量会不断增长。当单表数据达到数千万甚至上亿级别时查询性能、索引维护、数据备份和数据库扩容等问题都会逐渐显现。为了解决单表数据量过大的问题互联网系统通常会采用分库分表方案将数据按照一定规则拆分到多个数据库或数据表中。然而分库分表之后也会带来新的挑战例如如何确定数据应该存储到哪张表、如何跨表查询数据、如何降低业务代码的改造成本等。ShardingSphere正是为了解决这些问题而诞生的。它能够在应用层和数据库之间提供透明的分片能力让开发人员仍然像操作普通数据表一样进行开发而无需关心底层的数据路由和 SQL 改写过程。本文将结合 Spring Boot 和 MyBatis 项目从分库分表的背景开始逐步介绍 ShardingSphere 的核心概念、工作原理、项目集成方式、分片算法配置以及实际项目中的使用技巧帮助读者快速掌握 ShardingSphere 的基本使用与设计思路。shardingsphere官网shardingsphere HitHub地址一、为什么需要 ShardingSphere随着业务发展订单表、支付表、流水表的数据量会越来越大。例如有一张支付订单表CREATETABLEpay_info(idBIGINTPRIMARYKEY,order_noVARCHAR(64),user_idBIGINT,amountDECIMAL(18,2),create_timeDATETIME);如果每天产生 100 万条数据100万/天 ≈ 3000万/月 ≈ 3.6亿/年几年之后单表可能达到几十亿数据。此时会出现很多问题查询变慢索引变大备份恢复困难DDL操作耗时数据迁移困难因此需要进行分库分表最常见的方案按时间分表按用户分表按订单号分表而目前 Java 生态中最主流的分库分表框架之一就是 Apache ShardingSphere。二、什么是 ShardingSphereShardingSphere 是 Apache 顶级项目。它是一套数据库中间件生态主要功能包括分库分表读写分离分布式事务数据加密SQL 路由SQL 改写在 Spring Boot 项目中最常见的是ShardingSphere-JDBC其架构如下MyBatis ↓ ShardingSphere ↓ MySQL对于业务代码来说感知不到分表的存在三、ShardingSphere 解决了什么问题假设数据库中有以下表pay_info_202601 pay_info_202602 pay_info_202603 ...程序中仍然写select*frompay_info或者payInfoMapper.insert(payInfo);增删改查时 ShardingSphere 会自动帮你改写 SQL。例如createTime2026-05-15自动路由insertintopay_info_202605开发人员完全不需要手动判断表名。四、ShardingSphere 的核心概念1. 逻辑表程序中看到的表pay_info称为逻辑表。例如select*frompay_info2. 真实表数据库真正存在的表pay_info_202601 pay_info_202602 pay_info_202603称为真实表。3. 分片键决定数据进入哪张表的字段。例如create_time或者user_id或者order_no都可以作为分片键。4. 分片算法根据分片键计算目标表。例如2026-05-15计算得到pay_info_202605五、Spring Boot 集成 ShardingSphere1. 引入依赖dependencygroupIdorg.apache.shardingsphere/groupIdartifactIdshardingsphere-jdbc-core-spring-boot-starter/artifactId/dependency2. 配置数据源spring:shardingsphere:datasource:names:dsds:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/testusername:rootpassword:root这里的url username password就是实际数据库连接配置。3. 是否还需要 spring.datasource上面在 shardingsphere 下已经配置了数据源了是否还需要 spring.datasource 通常不需要。不要同时配置spring:datasource:和spring:shardingsphere:datasource:否则可能出现NoUniqueBeanDefinitionException因为 Spring 中会存在多个 DataSource Bean。六、配置真实表假设数据库已经存在pay_info_202601 pay_info_202602 ... pay_info_203012配置如下spring:shardingsphere:rules:sharding:tables:pay_info:actual-data-nodes:ds.pay_info_$-{202601..203012}含义逻辑表 pay_info 真实表 pay_info_202601 pay_info_202602 ... pay_info_203012七、按月份分表1. 配置分片策略table-strategy:standard:sharding-column:create_timesharding-algorithm-name:pay-info-month2. sharding-column 是什么表示根据哪个字段决定路由例如sharding-column:create_time表示根据 create_time 决定数据进入哪张表例如2026-05-20自动进入pay_info_2026053. 必须有 create_time 字段吗不一定。可以使用sharding-column:pay_time或者sharding-column:order_time只要能够表达时间即可。八、配置时间分片算法sharding-algorithms:pay-info-month:type:INTERVALprops:datetime-pattern:yyyy-MM-dd HH:mm:ssdatetime-lower:2025-01-01 00:00:00datetime-upper:2030-12-31 23:59:59sharding-suffix-pattern:yyyyMMdatetime-interval-unit:MONTHS1. datetime-pattern时间格式。yyyy-MM-dd HH:mm:ss例如2026-05-1815:20:302. datetime-lower开始时间2025-01-01 00:00:003. datetime-upper结束时间2030-12-31 23:59:594. sharding-suffix-pattern表后缀格式。例如yyyyMM生成pay_info_202605如果yyyy_MM生成pay_info_2026_055. datetime-interval-unit分片粒度。按月MONTHS生成pay_info_202605 pay_info_202606按天DAYS生成pay_info_20260501 pay_info_20260502按年YEARS生成pay_info_2025 pay_info_2026九、MyBatis 和 MyBatis Plus 如何使用1. Mapper 不需要修改例如MapperpublicinterfacePayInfoMapper{PayInfoselectById(Longid);}2. XML 不需要修改仍然写selectidselectByIdselect * from pay_info where id #{id}/select不要写pay_info_202605也不要写pay_info_202606统一写pay_info即可。3. ShardingSphere 自动改写 SQL程序select*frompay_info实际执行select*frompay_info_202605或者select*frompay_info_202605unionallselect*frompay_info_202606十、查询如何路由1. 精准路由例如select*frompay_infowherecreate_time2026-05-01andcreate_time2026-06-01只查询pay_info_202605性能最好。2. 范围路由例如select*frompay_infowherecreate_timebetween2026-05-01and2026-07-31查询pay_info_202605 pay_info_202606 pay_info_2026073. 全路由例如select*frompay_infowherestatus1没有分片键create_timeShardingSphere 无法判断目标表。于是pay_info_202601 pay_info_202602 ... pay_info_203012全部查询。这就是全路由性能极差。十一、每个 SQL 都必须带分片键吗不是必须。可以正常执行。但是不带分片键 全路由 查询所有分表因此在设计表结构时高频查询条件 最好就是分片键这样性能最高。十二、ShardingSphere 会自动创建表吗不会。ShardingSphere 负责SQL路由不负责创建表例如insertintopay_info路由到pay_info_202606如果pay_info_202606不存在。直接报错Table doesnt exist十三、如何自动创建分表1. 推荐方案提前创建未来几年表。例如pay_info_202601 ... pay_info_203012一次建好即可。2. 定时任务创建假设每月1号创建未来三个月的表1定时任务//每个月的 1 号凌晨 2 点整执行一次Scheduled(cron0 0 2 1 * ?)publicvoidcreateFutureTables(){//循环三次创建未来三个月的表for(inti1;i3;i){LocalDatemonthLocalDate.now().plusMonths(i);//检查表是否存在不存在则创建createTableIfNotExists(month);}}2模板表一般会准备一个模板表CREATETABLEpay_info_template(idBIGINTPRIMARYKEY,order_noVARCHAR(64),amountDECIMAL(18,2),create_timeDATETIME,KEYidx_create_time(create_time));(3) 使用 JdbcTemplate 创建表AutowiredprivateJdbcTemplatejdbcTemplate;privatevoidcreateTableIfNotExists(LocalDatemonth){StringtableNameString.format(pay_info_%d_%02d,month.getYear(),month.getMonthValue());StringsqlCREATE TABLE IF NOT EXISTS tableName LIKE pay_info_template;jdbcTemplate.execute(sql);}效果假设 当前是2026-05定时任务会执行CREATETABLEIFNOTEXISTSpay_info_202606LIKEpay_info_template;CREATETABLEIFNOTEXISTSpay_info_202607LIKEpay_info_templateCREATETABLEIFNOTEXISTSpay_info_202608LIKEpay_info_template最终创建了pay_info_2026_06 pay_info_2026_07 pay_info_2026_083. Flyway 或 Liquibase使用数据库版本管理工具自动创建。十四、生产环境如何设计分表1. 单纯按月份分表pay_info_202605 pay_info_202606 pay_info_202607适合按时间查询较多2. 按用户 Hash 分表pay_info_00 pay_info_01 ... pay_info_63路由userId%64适合根据用户查询较多3. 时间 Hash大型支付系统最常见。例如pay_info_202605_00 pay_info_202605_01 ... pay_info_202605_15优势控制单表大小查询效率高扩展能力强十五、ShardingSphere 的优缺点优点对业务代码侵入小MyBatis 基本不用改自动路由自动聚合结果支持读写分离支持分布式事务支持分库分表缺点配置复杂SQL 不宜过于复杂跨分片查询成本高全路由性能差分页查询需要特别注意十六、总结ShardingSphere 本质上是一个数据库中间层。对于开发人员来说仍然操作逻辑表 pay_info对于数据库来说实际访问真实表 pay_info_202605 pay_info_202606其核心思想只有一句话开发只关心逻辑表 ShardingSphere负责将SQL路由到正确的真实表。