海量数据存储与查询 MyCat(未完成)(三)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 海量数据存储与查询 MyCat(未完成)(三)

四、Mycat分片技术

4.1 垂直拆分-分库

前沿

目前很多互联网系统都存在单表数据量过大的问题,这就降低了查询速度,影响了客户体验。为了提高查询速度,我们可以优化sql语句,优化表结构和索引,不过对那些百万级千万级的数据库表,即便是优化过后,查询速度还是满足不了要求。

垂直分库

就是将不同业务的数据表存放到不同的数据库服务器中。

实现分库

我们选择master1和slave1作为存放不同表的服务器。但是需要注意的是这两个服务器是存在主从复制的,我们需要将这两个服务器的主从复制关掉。

mysql> stop slave;
#查看主从复制是否关闭
show slave status \G;

修改mycat配置文件schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
  <!-- 数据库配置 与server.xml 中的数据库对应 -->
    <schema name="db_test" checkSQLschema="false" dataNode="dn1" sqlMaxLimit="100">
      <!--如果是customer表就存放在dn2节点上,其他的表存放在dn1数据节点上-->
      <table name="customer" dataNode="dn2"/>
    </schema>
  <!-- 两个数据节点 dn1,2 上都要创建 orders 数据库 -->
    <dataNode name="dn1" dataHost="host1" database="orders" />
    <dataNode name="dn2" dataHost="host2" database="orders" />
  <!-- 两个数据库 肯定两个 dataHost -->
    <dataHost name="host1" maxCon="1000" minCon="10" balance="0"
             writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM1" url="192.168.66.100:3350" user="root"
                  password="123456">
        </writeHost>
    </dataHost>
    <dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM2" url="192.168.66.100:3360" user="root" password="123456">
        </writeHost>
    </dataHost>
</mycat:schema>

启动/重新启动mycat

mycat start/restart

开启3350和3360两个docker容器master1和slave1(此时两者不具备主从复制关系).

docker start master1
docker start slave1
#分别进入到容器
docker exec -it master1 /bin/bash
docker exec -it slave1/bin/bash
#分别进入两个数据库
mysql -uroot -p123456
#分别创建orders表
mysql> create database orders;

进入mycat,并创建表验证垂直分库

mysql -uroot -p123456 -h192.168.66.100 -P8066
create table customer(
  id int auto_increment,
  name varchar(200),
 primary key(id)
);
create table orders(
  id int auto_increment,
  order_type int,
  customer_id int,
  amount decimal(10,2),
 primary key(id)
);
create table orders_detail(
  id int auto_increment,
  order_id int,
  detail varchar(200),
 primary key(id)
);
create table dict_order_type(
  id int auto_increment,
  order_type varchar(200),
 primary key(id)
);

master1节点中的数据表

mysql> show tables;
+------------------+
| Tables_in_orders |
+------------------+
| dict_order_type  |
| orders           |
| orders_detail    |
+------------------+
3 rows in set (0.00 sec)

slave1节点中的数据表

mysql> show tables;
+------------------+
| Tables_in_orders |
+------------------+
| customer         |
+------------------+
1 row in set (0.00 sec)

综上,垂直分库成功!

4.2 水平拆分-分表

前言

上面谈到垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题。

水平拆分

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。

理解:

我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。

实现分表

1、 选择要拆分的表

MySQL 单表存储数据条数是有瓶颈的,单表达到 1000 万条数据就达到了瓶颈,会影响查询效率,需要进行水平拆分(分表)进行优化。

2、分表字段

以 orders 表为例,可以根据不同字段进行分表

编号 分表字段 效果
1 id 查询订单注重时效,历史订单被查询的次数少,如此分片会造成一个节点访问多,一个访问少,不平均。
2 customer_id 根据客户 id 去分,两个节点访问平均。

3、 修改配置文件 schema.xml

为 orders 表设置数据节点为 dn1、dn2,并指定分片规则为 mod_rule(自定义的名字)

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" dataNode="db_node1"  sqlMaxLimit="100">
       <table name="orders" dataNode="db_node1,db_node2" rule="mod_rule"/>
        </schema>
        <dataNode name="db_node1" dataHost="db_host1" database="orders" />
        <dataNode name="db_node2" dataHost="db_host2" database="orders" />
        <dataHost name="db_host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="192.168.66.100:3350" user="root" password="123456">   
                </writeHost>
        </dataHost>
        <dataHost name="db_host2" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="192.168.66.100:3360" user="root" password="123456">   
                </writeHost>
        </dataHost>
</mycat:schema>

4、修改配置文件rule.xml

分片规则:

在 rule 配置文件里新增分片规则 mod_rule,并指定规则适用字段为 customer_id, 还有选择分片算法 mod-long(对字段求模运算),customer_id 对两个节点求模,根据结果分片.配置算法 mod-long 参数 count 为 2,两个节点。

<tableRule name="mod_rule">
 <rule>
  <columns>customer_id</columns>
  <algorithm>mod-long</algorithm>
 </rule>
</tableRule>
<function name="mod-long"   class="io.mycat.route.function.PartitionByMod">
 <!-- 物理主机的节点数 -->
 <property name="count">2</property>
</function>

5、 重启Mycat,让配置生效

6、 在数据节点dn1,dn2上建orders表

create table orders(
  id int auto_increment,
  order_type int,
  customer_id int,
  amount decimal(10,2),
 primary key(id)
);

7、 连接mycat并添加数据

mysql -uroot -p123456 -h192.168.66.100 -P8066
INSERT INTO orders(id,order_type,customer_id,amount) VALUES (1,101,100,100100);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);

在mycat中可以看到全部的6条数据,但是在两个节点中只能看到3条数据。

4.3 ER表

分片 join

在上一小结主要是实现了数据表的水平拆分,但是在做表和表之间的连接查询的时候会出问题,假设我们用orders表和orders_details表做关联查询,sql发送到mycat的时候发现orders表做水平拆分后出现在好几个数据库服务器中,于是就将sql发送给这些服务器,但是有些服务器不存在orders_detilas表,执行sql会返回错误。这就是分片join错误。

ER 表

将子表的存储位置依赖于主表,并且物理上紧邻存放因此彻底解决了JION的效率和性能问题,根据这一思路,提出了基于E-R关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上。说人话就是我们将表和表之间基于某种关系或指定分为子表和父表,mycat会将子表的数据存放在含有父表的数据库服务器上。

修改配置文件schema.xml配置父子关系

<schema name="TESTDB" checkSQLschema="false" dataNode="db_node1"  sqlMaxLimit="100">
       <table name="orders" dataNode="db_node1,db_node2" rule="mod_rule">
             #childTable:子表
            <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
       </table>
 </schema>

重启Mycat服务

mycat restart

分别在两个数据库中创建orders数据库,其中一个数据库不含orders_detail表

向mycat中添加数据

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
存储 SQL 关系型数据库
高效访问数据的关键:解析MySQL主键自增长的运作机制!
高效访问数据的关键:解析MySQL主键自增长的运作机制!
|
9月前
|
存储 关系型数据库 MySQL
海量数据存储与查询 MyCat(未完成)(二)
海量数据存储与查询 MyCat(未完成)(二)
|
13天前
|
存储 关系型数据库 MySQL
如何处理爬取到的数据,例如存储到数据库或文件中?
处理爬取的数据,可存储为txt、csv(适合表格数据)或json(适合结构化数据)文件。若需存储大量数据并执行复杂查询,可选择关系型(如MySQL)或非关系型(如MongoDB)数据库。以MySQL为例,需安装数据库和Python的pymysql库,创建数据库和表,然后编写Python代码进行数据操作。选择存储方式应考虑数据类型、数量及后续处理需求。
21 1
|
4月前
|
存储 NoSQL 数据挖掘
请解释一下列存储数据库的工作原理,并提供一个使用列存储数据库的实际应用场景。
请解释一下列存储数据库的工作原理,并提供一个使用列存储数据库的实际应用场景。
53 0
|
5月前
|
存储 关系型数据库 MySQL
史上最全MySQL剖析:优化+存储+查询+索引+复制+可扩展+高可用
在互联网行业,MySQL数据库毫无疑问已经是最常用的数据库,LAMP (Linux +Apache + MySQL + PHP)甚至已经成为专有名词,也是很多中小网站建站的首选技术架构。
|
7月前
|
存储 关系型数据库 MySQL
30分布式电商项目 - 一亿条数据插入MySQL,耗时多少?
30分布式电商项目 - 一亿条数据插入MySQL,耗时多少?
60 0
|
9月前
|
SQL 关系型数据库 MySQL
海量数据存储与查询 MyCat(未完成)(一)
海量数据存储与查询 MyCat(未完成)(一)
|
10月前
|
SQL 关系型数据库 MySQL
【项目实现典型案例】12.数据库数据类型不一致导致查询慢
【项目实现典型案例】12.数据库数据类型不一致导致查询慢
|
10月前
|
存储 前端开发 中间件
应用数据库常见的数据切分方式
应用数据库常见的数据切分方式
91 0
|
12月前
|
SQL JavaScript Java
高效方案:30万条数据插入 MySQL 仅需13秒
高效方案:30万条数据插入 MySQL 仅需13秒