垂直拆分,解决了单库容量过大的问题,但是对于单表记录过大的问题,并没有解决。
1 水平拆分
按照数据表中某个字段的某种规则,将记录分散到多个库中,每个库该表中存储一部分记录,所有库中该表的记录并集,为该表所有记录的数据全集。
可以将其理解为按照数据的行进行拆分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。
2 实现分表
2.1 选择要拆分的表
MySQL单表存储数据条数,是存在瓶颈的。当单表数据达到1000万条时就会到达性能瓶颈,对查询效率有明显影响。此时,需要对该表做水平拆分的优化。
2.2 分析用来做分表的字段
以前边创建的 orders 表为例,可以根据不同的字段进行分表。
分表字段 | 效果 |
---|---|
id | 对于整个系统来说,所有订单都会被平衡地拆分到不同数据库中,但是结合使用场景,这个查询系统中所有订单的操作,没有实际价值,因为该项操作仅支持系统管理员操作 |
customer_id | 将用户的订单平衡地拆分到不同数据库中。用户在下完订单后,对订单进行查询,该项操作的查询会非常频繁,如果根据该字段进行拆分,将极大提高查询效率,提升用户体验 |
2.3 修改配置文件 schema.xml
为数据表 orders 设置数据节点 dn1、dn2,并定义分片规则的名称为 customer_id_rule。
增加一个 table 节点:
- name 为哪个数据表设置该分片规则,这里是 orders 表;
- dataNode 将该表存储的位置,这里是同时存储于 dn1、dn2 节点;
- rule 对表中数据水平拆分的规则,这里是规则名称,对应于 rule.xml 中的配置。
2.4 修改配置文件 rule.xml
在rule.xml配置文件中,增加名称为 customer_id_rule 的规则信息。
2.4.1 增加tableRule节点
添加用于水平拆分的规则名称:
- columns 根据哪个字段来进行水平拆分;
- algorithm 计算拆分的具体算法,该数据对应 rule.xml 配置文件中的一个 function 节点。
<tableRule name="customer_id_rule">
<rule>
<columns>customer_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
2.4.2 修改function节点
该节点是用于设置对数据存储分片的计算规则。
可以选择添加新的function节点,或者在确保对其他设置没有影响时,修改已有的function节点。
- name 规则计算的名称,应与上一部分 algorithm 节点值一致;
- class 调用规则计算的java类,这里使用的是取模运算 PartitionByMod;
- property name="count" 要分片的节点数量。
通过这种设置后,即我们有两台数据库节点,在存储数据时,先做 x % 2 运算,当值为0时存储 dn1,值为1时存储到 dn2。
代码语言:html复制<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
2.5 为dn2节点创建数据表
因之前做分库时,仅将 orders 表保存到了 dn1 节点,这里需要在 dn2 节点中也创建 orders 表。
进入到 dn2 容器
docker exec -it db2 /bin/bash
进入到数据库命令行
mysql -uroot -p123456
创建 orders 表
create table orders(id int auto_increment primary key, order_type int, customer_id int, amount decimal(10,2));
2.6 重新启动mycat
mycat restart2.7 向orders表中批量插入数据
2.7.1 进入到mycat数据端口
mysql -uroot -p123456 -h192.168.137.3 -P8066
批量插入数据
insert into orders(id, order_type, customer_id, amount) values(1, 101, 100, 258.12);
insert into orders(id, order_type, customer_id, amount) values(2, 101, 101, 1543.0);
insert into orders(id, order_type, customer_id, amount) values(3, 101, 101, 57.03);
insert into orders(id, order_type, customer_id, amount) values(4, 101, 100, 5000);
insert into orders(id, order_type, customer_id, amount) values(5, 101, 100, 923);
insert into orders(id, order_type, customer_id, amount) values(6, 101, 102, 7583);
2.7.2 在mycat查询数据
2.7.3 在dn1节点查询数据
2.7.4 在dn2节点查询数据
所有插入的数据,根据 customer_id 在 dn1 和 dn2 节点进行了水平拆分。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!