1. 项目地址
2. 配置文件
# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.config-location=classpath:mybatis-config.xml
spring.shardingsphere.props.sql.show=true
# 数据源配置
spring.shardingsphere.datasource.names=ds0,ds1
spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.url=jdbc:mysql://****:3306/ds0
spring.shardingsphere.datasource.ds0.username=****
spring.shardingsphere.datasource.ds0.password=****
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://****:3306/ds1
spring.shardingsphere.datasource.ds1.username=****
spring.shardingsphere.datasource.ds1.password=****
# 分片策略 (行表达式分片策略InlineShardingStrategy)
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds${user_id % 2}
# 分库算法 user_info,多库分表
# 只分库但没有分表 分库是真正有作用的,但是如果在一个库里进行了分表,意义不是很大。
# 如果针对同一个表,既分库又分表,比如ds0.user_info_0,ds0.user_info_1,ds1.user_info_0,ds1.user_info_1
# 如果针对useid进行模2为0落到ds0.user_info_0,为1落到ds1.user_info_1,则ds0.user_info_1,ds1.user_info_0就会用不到,对吧。
# 所以只分库不分表是很合理的,不管分的库是在同一个服务器还是不同的服务器都可以。
spring.shardingsphere.sharding.tables.user_info.actual-data-nodes=ds$->{0..1}.user_info
# 分片键
spring.shardingsphere.sharding.tables.user_info.databaseStrategy.inline.shardingColumn=user_id
# 分库的算法是用ds拼接[user_id模2]
spring.shardingsphere.sharding.tables.user_info.databaseStrategy.inline.algorithm-expression=ds${user_id % 2}
spring.shardingsphere.sharding.tables.user_info.key-generator.column=user_id
spring.shardingsphere.sharding.tables.user_info.key-generator.type=SNOWFLAKE
# 分库算法 t_order 多库分表
spring.shardingsphere.sharding.tables.t_order.databaseStrategy.inline.shardingColumn=order_id
spring.shardingsphere.sharding.tables.t_order.databaseStrategy.inline.algorithm-expression=ds${order_id % 2}
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order
# 分库算法 t_order_item 多库分表
spring.shardingsphere.sharding.tables.t_order_item.databaseStrategy.inline.shardingColumn=order_id
spring.shardingsphere.sharding.tables.t_order_item.databaseStrategy.inline.algorithm-expression=ds${order_id % 2}
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item
# 绑定表规则列表,防止关联查询出现笛卡尔积
spring.shardingsphere.sharding.binding-tables[0]=t_order,t_order_item
# 广播表
spring.shardingsphere.sharding.broadcast-tables=t_config
3. 测试
3.1 普通的user_id分片
//部分代码
public void insert() {
for (int i = 1; i <= 100; i++) {
UserInfo userInfo = new UserInfo();
// userInfo.setUserId(userId); //会使用sharding-jdbc自带的生成的全局ID
userInfo.setAccount("account" + i);
userInfo.setPassword("password" + i);
userInfo.setUserName("name" + i);
userId++;
userInfoMapper.insert(userInfo);
}
}
执行insert方法:添加100条user_info数据(一个库中有50条)
查询:
@Test
public void select(){
UserInfo userInfo1= userService.getUserInfoByUserId(582609201549803521l);
System.out.println("------userInfo1:"+userInfo1);
UserInfo userInfo2= userService.getUserInfoByUserId(582609200694165504l);
System.out.println("------userInfo2:"+userInfo2);
}
3.2 绑定表(t_order,t_order_item)
//t_order新增
public void insert() {
for (int i = 1; i <= 100; i++) {
Order order = new Order();
order.setOrderId(i);
order.setUserId(i);
orderId++;
userId++;
orderMapper.insert(order);
}
}
//t_order_item新增
public void insert() {
for (int i = 1; i <= 100; i++) {
OrderItem orderItem = new OrderItem();
orderItem.setItemId(i);
orderItem.setOrderId(i);
orderItem.setUserId(i);
orderItemMapper.insert(orderItem);
}
}
注意这个配置:
# 绑定表规则列表,防止关联查询出现笛卡尔积
spring.shardingsphere.sharding.binding-tables[0]=t_order,t_order_item
如果不配置它会出现 笛卡尔积,什么叫笛卡尔积?假如有 2 个数据库,两张表要相互关联,两张表又各有分表,那 么 SQL 的执行路径就是 222=8 种。如果针对同一个表,既分库又分表,比如
ds0.order0,ds0.order1,
ds0.order_item0,ds0.order_item1
ds1.order_0,ds1.order_1,
ds1.order_item_0,ds1.order_item_1
会出现,多出几次无效查询
如果配置了绑定规则,
3.3 全局表
//插入10条数据
public void insert() {
for (int i = 1; i <= 10; i++) {
Config config = new Config();
config.setConfigId(i);
config.setParaName("name"+i);
config.setParaValue("value"+i);
config.setParaDesc("desc"+i);
configId++;
configMapper.insert(config);
}
}