1、使用场景
Merge表有点相似于视图。使用Merge存储引擎实现MySQL分表,这种方法比较适合那些没有事先考虑分表,随着数据的增多,已经出现了数据查询慢的状况。这个时候若是要把已有的大数据量表分开比较痛苦,最痛苦的事就是改代码。因此使用Merge存储引擎实现MySQL分表能够避免改代码。
Merge引擎下每一张表只有一个MRG文件。MRG里面存放着分表的关系,以及插入数据的方式。它就像是一个外壳,或者是链接池,数据存放在分表里面。
merge合并表的要求:
- 合并的表使用的必须是MyISAM引擎
- 表的结构必须一致,包括索引、字段类型、引擎和字符集
对于增删改查,直接操做总表便可。
2、建表
1.用户1表
CREATE TABLE `user1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `sex` int(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
2.用户2表
create table user2 like user1;
3.主表
CREATE TABLE `alluser` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `sex` int(1) NOT NULL DEFAULT '0', KEY `id` (`id`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 INSERT_METHOD=LAST UNION=(`user1`,`user2`);
1) ENGINE = MERGE 和 ENGINE = MRG_MyISAM是同样的意思,都是表明使用的存储引擎是 Merge。
2) INSERT_METHOD,表示插入方式,取值能够是:0 和 1,0表明不容许插入,1表明能够插入;
3) FIRST插入到UNION中的第一个表,LAST插入到UNION中的最后一个表。
3、操做
1. 先在user1表中增长一条数据,而后再在user2表中增长一条数据,查看 alluser中的数据。
insert into user1(name,sex) values ('张三',1);
insert into user2(name,sex) values ('李四',2);
select * from alluser; 发现是刚刚插入的数据以下:
这就出现了一个id重复,这就形成了当删除和修改的时候异常,解决办法是给 alluser的id赋惟一值。
咱们解决方法是,从新创建一张表tb_ids(id int),用来专门存一个id的,并插入一条初始数据,同时删除掉user1和user2中的数据。
create table tb_ids(id int); insert into tb_ids values(1); delete from user1; delete from user2;
而后在user1和user2表中分别创建一个触发器(tr_seq和tr_seq2),触发器的功能是 当在user1或者user2表中增长一条记录时,取出tb_ids中的id值,赋给user1和user2的id,而后将tb_ids的id值加1,
user1表的触发器内容以下(user2表的触发器修要修改 触发器的名字 和 表名,以下红字标注):
DELIMITER $$ CREATE TRIGGER tr_seq BEFORE INSERT on user1 FOR EACH ROW BEGIN select id into @testid from tb_ids limit 1; update tb_ids set id = @testid + 1; set new.id = @testid; END$$ DELIMITER;
2.在user1和user2表中分别增长一条数据,
insert into user1(name,sex) values('王五',1);
insert into user2(name,sex) values('赵六',2);
3.查询user1和user2中的数据:
4.查询总表alluser中的数据,发现id没有重复的:
搞定。
7、垂直切分的依据
当一个表属性不少时,如何来进行垂直拆分呢?若是没有特殊状况,拆分依据主要有几点:
(1)将长度较短,访问频率较高的属性尽可能放在一个表里,这个表暂且称为主表
(2)将字段较长,访问频率较低的属性尽可能放在一个表里,这个表暂且称为扩展表
若是1和2都知足,还能够考虑第三点:
(3)常常一块儿访问的属性,也能够放在一个表里
优先考虑1和2,第3点不是必须。另,若是实在属性过多,主表和扩展表均可以有多个。
通常来讲,数据量并发量比较大时,数据库的上层都会有一个服务层。须要注意的是,当应用方须要同时访问主表和扩展表中的属性时,服务层不要使用join来连表访问,而应该分两次进行查询:
缘由是,大数据高并发互联网场景下,通常来讲,吞吐量和扩展性是主要矛盾:
(1)join更消损耗数据库性能
(2)join会让base表和ext表耦合在一块儿(必须在一个数据库实例上),不利于数据量大时拆分到不一样的数据库实例上(机器上)。毕竟减小数据量,提高性能才是垂直拆分的初衷。
为何要这么这么拆分?
为什么要将字段短,访问频率高的属性放到一个表内?为什么这么垂直拆分能够提高性能?由于:
(1)数据库有本身的内存buffer,会将磁盘上的数据load到内存buffer里(暂且理解为进程内缓存吧)
(2)内存buffer缓存数据是以row为单位的
(3)在内存有限的状况下,在数据库内存buffer里缓存短row,就能缓存更多的数据
(4)在数据库内存buffer里缓存访问频率高的row,就能提高缓存命中率,减小磁盘的访问
举个例子就很好理解了:
假设数据库内存buffer为1G,未拆分的user表1行数据大小为1k,那么只能缓存100w行数据。
若是垂直拆分红user_base和user_ext,其中:
(1)user_base访问频率高(例如uid, name, passwd, 以及一些flag等),一行大小为0.1k
(2)user_ext访问频率低(例如签名, 我的介绍等),一行大小为0.9k
那边内存buffer就就能缓存近乎1000w行user_base的记录,访问磁盘的几率会大大下降,数据库访问的时延会大大下降,吞吐量会大大增长。
如何联合查找?
分库分表的结果会使数据分散,很差查询,主要有两种查询方式:
(1)分步查:先查找主表,而后获得关联表的id,再发起请求获得关联数据;
(2)联合查:同时发起多个查询请求,而后将全部的结果集合起来。
总结
(1)水平拆分和垂直拆分都是下降数据量大小,提高数据库性能的常见手段
(2)流量大,数据量大时,数据访问要有service层,而且service层不要经过join来获取主表和扩展表的属性
(3)垂直拆分的依据,尽可能把长度较短,访问频率较高的属性放在主表里
8、参考
一、https://www.jianshu.com/p/3fed6db29a01
二、https://www.cnblogs.com/butterfly100/p/9034281.html
三、https://blog.csdn.net/cfy1024/article/details/80899189
四、https://www.cnblogs.com/sunny3096/p/8595058.html
五、https://www.cnblogs.com/xbq8080/p/6628034.html
六、https://blog.csdn.net/wufaliang003/article/details/78619266