1 问题
随着我们的系统用户不断增加,产出的内容和数据量将不断增长,单台数据库数据量因为过大,将会导致查询速率降低,严重影响用户体验。
为了提高查询速度,可以优化查询的SQL语句,加大数据库服务器的内存,优化数据库表结构和索引,虽然能从一定程度上使效率得到提升,但对于数据记录达到千万级的数据表,其优化的效果仍会大打折扣。
2 垂直拆分
2.1 垂直分表
将数据表按列拆分,可将一张列比较多的表拆分为多张表。
当一个表记录虽不多,但字段较多,致使表占用的空间大,检索表的时候会占用大量的IO,严重降低数据库性能。此时,就可以把该表拆分为多个不同的表,这些多个表,应与原表保持一对一的关系。
拆分的原则:
- 把不常用的字段单独放在一张表;
- 把 text, blob 等含有大量信息的字段拆分出来放在附表中;
- 经常组合查询的列,放在同一张表中。
如下用户表中
如果只想要查询昵称为“孙悟空”的用户名,可以使用SQL语句:
SELECT 用户名 FROM 用户表 where 昵称=孙悟空;
这里虽然仅查询了用户名,但是在对记录进行扫描时,地址和订单信息这两个含有大量信息的字段也会被扫描到,增加了性能损耗。此时就是可以使用垂直拆分,将不想查询的字段拆分到另外的表中。
出现这种问题,多是因为最初对数据表的设计不合理导致。如果做好表的设计,该种拆分方式目前的应用并不多。
2.2 垂直分库
以数据表为区分依据,将实现不同业务的表,拆分到不同的数据库分片中。这种拆分方式应用最广。
不同数据库分片拥有不同的数据表,数据库的名称相同,我们的全量数据等于所有数据库分片的并集。
3 垂直拆分的实现
3.1 修改配置
修改 schema.xml 文件。
3.1.1 schema节点
在 schema 节点中将 dataNode 属性配置为 dn1;
并在 schema 下增加 table 节点,并配置以下属性:
- name 需要单独配置的数据表名称
- dataNode 需要单独配置的数据表所在服务器节点,如 dn2
在 table 节点设置的表,将存储在 dn2 节点,而没有被列出的表,都将存储在 dn1 节点。
3.1.2 dataNode节点
该节点用于分片设置。
一个分片节点对应于一条 dataNode 设置。所有 dataNode 节点应配置为同一个 database。
3.1.3 dataHost节点
dataHost 节点名称应与上一步中配置的 dataNode 节点中 dataHost 一致,且数量也应一致,这里应配置两个 dataHost 节点。
为了简化配置,删掉之前做的实现读写分离相关的配置信息。
修改后的配置信息如下:
3.2 创建数据库
为了简化学习难度,这里需要删除之前的相关服务并重新安装MYSQL。
3.2.1 环境清理
清理之前做双主双从数据库。
停止所有docker容器
docker stop $(docker ps -qa)
删除所有docker容器
docker rm $(docker ps -qa)
删除完成后,通过以下指令已查询不到任何容器
docker ps -a
3.2.2 安装数据库
以容器方式安装两个数据库服务:db1 和 db2
docker run -d -p 3366:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=db1 mysql:5.7
docker run -d -p 3366:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=db1 mysql:5.7
3.2.3 创建数据库
在数据库db1和db2中分别创建数据库 orders。
docker exec -it db1 /bin/bash
mysql -uroot -p123456
create database orders;
4 环境验证
4.1 启动mycat
使用mycat指令启动服务。
mycat start
如果服务启动失败,可以到 logs 目录下查看日志。
一般错误日志会输出到 .gz 后缀的压缩文件中,可以使用 gunzip 指令解压后查看。
4.2 进入mycat数据端口
mysql -uroot -p123456 -h192.168.137.3 -P8066
4.3 创建数据表
执行创建表的SQL语句。
创建customers表
create table customers(id int auto_increment primary key, name varchar(200));
创建orders表
create table orders(id int auto_increment primary key, order_type int, customer_id int, amount decimal(10,2));
在db1中查看数据表
在db2中查看数据表
在mycat中查看数据表
4.4 需要注意的是
db2中看到表名为全大写 CUSTOMERS,
而mycat中表名为 customers,
如果要在mycat中操作db2中CUSTOMERS 表的数据时,表名需要大写,才能访问到db2库的数据。
猜测可能是mycat的一个BUG。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!