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