Mycat中间件水平垂直切分,ER表,全局表

垂直拆分——分库

一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,
分布到不同 的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:
在这里插入图片描述
系统被切分成了,用户,订单交易,支付几个模块。

如何划分表
节点dn1建立customer表
节点dn2建立orders, orders_detail dict_order_type 3张表
建表语句

#客户表 rows:20万
CREATE TABLE customer(
 id INT AUTO_INCREMENT,
 NAME VARCHAR(200),
 PRIMARY KEY(id)
);
#订单表 rows:600万
CREATE TABLE orders(
 id INT AUTO_INCREMENT,
 order_type INT,
 customer_id INT,
 amount DECIMAL(10,2),
 PRIMARY KEY(id)
); 
#订单详细表 rows:600万
CREATE TABLE orders_detail(
 id INT AUTO_INCREMENT,
 detail VARCHAR(2000),
 order_id INT,
 PRIMARY KEY(id)
);
#订单状态字典表 rows:20
CREATE TABLE dict_order_type(
 id INT AUTO_INCREMENT,
 order_type VARCHAR(200),
 PRIMARY KEY(id)
);

修改 schema 配置文件

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
    <!-- 垂直分表customer表 在dn2节点上 -->
    <table name="customer" dataNode="dn2" ></table>
	</schema>
	
 	<!-- dn1节点 -->
	<dataNode name="dn1" dataHost="host1" database="orders" />
 <!-- dn2节点 -->
  <dataNode name="dn2" dataHost="host2" database="orders" />
	
 <!-- dn1节点数据库host1信息 -->
	<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.174.130:3306" user="root"
				   password="123456">
		</writeHost>
	</dataHost>
 
  <!-- dn2节点数据库host2信息 -->
 <dataHost name="host2" maxCon="1000" minCon="10" balance="0"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- can have multi write hosts -->
		<writeHost host="hostM2" url="192.168.174.10:3306" user="root"
				   password="123456">
		</writeHost>
	</dataHost>
 
</mycat:schema>

启动mycat用Navicat连接mycat 运行如下语句出现4张表则成功;
在这里插入图片描述

水平切分

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,
每个表中 包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就
是将表中的某些行切分 到一个数据库,而另外的某些行又切分到其他的数据库中,
在这里插入图片描述

实现水平分表
将orders 水平切分到 dn1,dn2节点上,根据customer_id取模

修改 schema.xml

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
    <!-- 垂直分表customer表 在dn2节点上 -->
    <table name="customer" dataNode="dn2" ></table>
    <!-- 水平分表orders表 为 orders 表设置数据节点为 dn1、dn2,并指定分片规则为在rule.xml中 mod_rule(自定义的名字) -->
    <table name="orders" dataNode="dn1,dn2" rule="mod_rule" ></table>
	</schema>
	
 	<!-- dn1节点 -->
	<dataNode name="dn1" dataHost="host1" database="orders" />
 <!-- dn2节点 -->
  <dataNode name="dn2" dataHost="host2" database="orders" />
	
 <!-- dn1节点数据库host1信息 -->
	<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.174.130:3306" user="root"
				   password="123456">
		</writeHost>
	</dataHost>
 
  <!-- dn2节点数据库host2信息 -->
 <dataHost name="host2" maxCon="1000" minCon="10" balance="0"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- can have multi write hosts -->
		<writeHost host="hostM2" url="192.168.174.10:3306" user="root"
				   password="123456">
		</writeHost>
	</dataHost>
 
</mycat:schema>

修改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">
 <!-- how many data nodes  目前只有2个节点所以改成2 -->
 <property name="count">2</property>
 </function>

然后再dn2上建立orders表
重启mycat,用navcat连接mycat,插入语句

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);

然后再dn1和dn2中的orders表可以查看到数据成功

ER表

Orders 订单表已经进行分表操作了,和它关联的 orders_detail 订单详情表如何进行 join 查询。
Mycat 借鉴了 NewSQL 领域的新秀 Foundation DB 的设计思路,Foundation DB 创新性的提
出了 Table Group 的概念,其将子表的存储位置依赖于主表,并且物理上紧邻存放,因此彻底解决了
JION 的效率和性能问 题,根据这一思路,提出了基于 E-R 关系的数据分片策略,子表的记录与所
关联的父表记录存放在同一个数据分片上。

修改schema.xml

<table name="orders" dataNode="dn1,dn2" rule="mod_rule" >
 <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
</table>

在dn1上建立orders_detail
重启 Mycat
插入数据

INSERT INTO orders_detail(id,detail,order_id) values(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);

然后运行join查询

Select o.*,od.detail from orders o inner join orders_detail od on o.id=od.order_id;

全局表

在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表之间的关联,
就成了比较 棘手的问题,考虑到字典表具有以下几个特性:
① 变动不频繁
② 数据量总体变化不大
③ 数据规模不大,很少有超过数十万条记录
鉴于此,Mycat 定义了一种特殊的表,称之为“全局表”,全局表具有以下特性:
① 全局表的插入、更新操作会实时在所有节点上执行,保持各个分片的数据一致性
② 全局表的查询操作,只从一个节点获取
③ 全局表可以跟任何一个表进行 JOIN 操作
将字典表或者符合字典表特性的一些表定义为全局表,则从另外一个方面,很好的解决了数据
JOIN 的难题。通过全局表+基于 E-R 关系的分片策略,Mycat 可以满足 80%以上的企业应用开发

修改 schema.xml 配置文件
添加如下语句

<table name="dict_order_type" dataNode="dn1,dn2" type="global" ></table>

在这里插入图片描述
在 dn1 创建 dict_order_type 表
重启mycat
插入数据

INSERT INTO dict_order_type(id,order_type) VALUES(101,'type1');
INSERT INTO dict_order_type(id,order_type) VALUES(102,'type2');

#在Mycat、dn1、dn2中查询表数据
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值