引言
上一篇:Sharding-JDBC实现Mysql读写分离实战演示 中,咱们使用读写分离,将数据库查询的压力分担到从库中,但是,如果单表的数据量非常的大,超过1000万行了,通过单表的优化,已经无法显著的优化性能,此时就要考虑分表了。
官方文档地址:shardingsphere官方文档
1、环境准备
本项目在上一篇项目的基础上进行修改,如下:
- 数据库脚本准备
USE `coolsummermoon`;
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (
`id` bigint(18) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (
`id` bigint(18) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `user_2`;
CREATE TABLE `user_2` (
`id` bigint(18) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
- 修改application.yml
sharding:
jdbc:
datasource:
names: db-master,db-slave
db-master:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.158.129:3306/coolsummermoon?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
username: root
password: 123456
maxPoolSize: 20
db-slave:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.158.131:3306/coolsummermoon?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
username: root
password: 123456
maxPoolSize: 20
props:
sql:
show: true
config:
sharding:
tables:
user:
actual-data-nodes: db_0.user_$->{
0..2}
table-strategy:
inline:
sharding-column: id
algorithm-expression: user_${
id.longValue() % 3}
master-slave-rules:
db_0:
master-data-source-name: db-master
slave-data-source-names: db-slave
server:
port: 8010
mybatis:
type-aliases-package: com.comcoolsummermoon.entity
mapper-locations: classpath:mapper/*.xml
- Controller
@RestController
@RequestMapping("users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/list")
public Object list() {
return userService.list();
}
@GetMapping("/insert")
public Object insert() {
for(long i=1; i<100; i++) {
User user = new User();
//注意此处增加了主键id,因为分表的规则是对id除以3取余
user.setId(i);
user.setUsername("coolsummermoon" + i);
user.setPassword("123456");
userService.insert(user);
}
return true;
}
}
4、UserMapper.xml
insert的语句中一定要加上id(特别强调,这里一定要加id,你可以不加试试),因为sharding的规则是对jdbc进行重写,并且是以id作为分表的策略
<insert id="insert" parameterType="com.comcoolsummermoon.entity.User">
insert into user (id,username, password)
values (#{id,jdbcType=BIGINT},#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR})
</insert>
- 除上面标注的部分,其余和上一篇项目一致
2、测试
- 启动项目工程,调用插入接口
- 打开master数据库,三个表中的数据,都按照分表规则插入成功
- 打开slave数据库,三个表的数据都备份成功
- 调用查询接口,成功返回数据,数据的格式是先返回user_0、user_1、user_2中的数据进行排序,如果想要按照id从小到大排序,则需要修改查询sql,增加:order by id
结束语
想要了解更详细的配置,可以参考文章开头的官方文档。
留一个思考题:本篇是以id作为分表的策略,如果是其它字段,如何保证主键的唯一性呢?