mysql--分表
mysql分表場景分析與簡單分表操作
為什麽要分表
首先要知道什麽情況下,才需要分表個人覺得單表記錄條數達到百萬到千萬級別時就要使用分表了,分表的目的就在於此,減小數據庫的負擔,縮短查詢時間.
表分割有兩種方式:
1水平分割:根據一列或多列數據的值把數據行放到兩個獨立的表中。
水平分割通常在下面的情況下使用:
表很大,分割後可以降低在查詢時需要讀的數據和索引的頁數,同時也降低了索引的層數,提高查詢速度。
表中的數據本來就有獨立性,例如表中分別記錄各個地區的數據或不同時期的數據,特別是有些數據常用,而另外一些數據不常用。
需要把數據存放到多個介質上。
水平分割會給應用增加復雜度,它通常在查詢時需要多個表名,查詢所有數據需要union操作。在許多數據庫應用中,這種復雜性會超過它帶來的優點,因為只要索引關鍵字不大,則在索引用於查詢時,表中增加兩到三倍數據量,查詢時也就增加讀一個索引層的磁盤次數。
2垂直分割:把主碼和一些列放到一個表,然後把主碼和另外的列放到另一個表中。
如果一個表中某些列常用,而另外一些列不常用,則可以采用垂直分割,另外垂直分割可以使得數據行變小,一個數據頁就能存放更多的數據,在查詢時就會減少I/O次數。 其缺點是需要管理冗余列,查詢所有數據需要join操作。
場景案例:
博客系統
垂直分割:
文章標題,作者,分類,創建時間等,是變化頻率慢,查詢次數多,而且最好有很好的實時性的數據,我們把它叫做冷數據。
而博客的瀏覽量,回復數等,類似的統計信息,或者別的變化頻率比較高的數據,我們把它叫做活躍數據。
所以,在進行數據庫結構設計的時候,就應該考慮分表,首先是縱向分表的處理。
這樣縱向分表後:
首先存儲引擎的使用不同,冷數據使用MyIsam 可以有更好的查詢數據。活躍數據,可以使用Innodb ,可以有更好的更新速度。
其次,對冷數據進行更多的從庫配置,因為更多的操作是查詢,這樣來加快查詢速度。對熱數據,可以相對有更多的主庫的橫向分表處理。
其實,對於一些特殊的活躍數據,也可以考慮使用memcache ,redis之類的緩存,等累計到一定量再去更新數據庫.
水平分割:
當博客的量達到很大時候,就應該采取橫向分割來降低每個單表的壓力,來提升性能。
例如博客的冷數據表,假如分為100個表,當同時有100萬個用戶在瀏覽時,如果是單表的話,會進行100萬次請求,而現在分表後,就可能是每個表進行1萬個數據的請求(因為,不可能絕對的平均,只是假設),這樣壓力就降低了很多很多。
mysql分表的方法: http://blog.csdn.net/heirenheiren/article/details/7896546
使用Merge存儲引擎展示水平分表實例:
查看mysql的存儲引擎
mysql> show engines \G;
現實場景模擬
第一步:
DROP table IF EXISTS member; create table member( id bigint auto_increment primary key, name varchar(20), sex tinyint not null default ‘0‘ )ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
第二步:創建存儲過程,插入百萬數據
#如果存在已定義的存儲過程inserts,刪除掉 drop procedure IF EXISTS inserts; #自定義結束符 delimiter // #創建存儲過程 create procedure inserts() begin DECLARE i int; set i = 1; WHILE(i <= 10) DO insert into member(name,sex) values(concat(‘name‘,i),i%2); SET i = i+1; END WHILE; end; #使用自定義結束符結束存儲過程定義 // #還原結束符為; delimiter ; #調用存儲過程 call inserts();
MySQL的語法默認使用分號";"作為一條SQL語句結束的標誌.可以使用delimiter命令將其修改成其他符號,如:"delimiter //" 表示以//作為提交符號.
為了演示分表,所以實例中插入10條數據模擬.
第三步:創建分表
#分表1# DROP table IF EXISTS tb_member1; create table tb_member1( id bigint primary key auto_increment , name varchar(20), sex tinyint not null default ‘0‘ )ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; #分表2# DROP table IF EXISTS tb_member2; #復制表1 create table tb_member2 like tb_member1;
第四步:創建主表,這裏主表的定義與要分的目標表有不同
#主表# DROP table IF EXISTS tb_member; create table tb_member( id bigint auto_increment , name varchar(20), sex tinyint not null default ‘0‘, INDEX(id) )ENGINE=MERGE UNION=(tb_member1,tb_member2) INSERT_METHOD=LAST AUTO_INCREMENT=1 ;
查詢tb_member表的索引信息
mysql> show index from tb_member \G;
第五步:將目標表數據分到兩個分表中去
INSERT INTO tb_member1(tb_member1.id,tb_member1.name,tb_member1.sex) SELECT member.id,member.name,member.sex FROM member where member.id%2=0 ; INSERT INTO tb_member2(tb_member2.id,tb_member2.name,tb_member2.sex) SELECT member.id,member.name,member.sex FROM member where member.id%2=1 ;
當然實際場景根據需要進行唯一標識操作,取hash啊什麽的等等,這裏只使用簡單去求模分表.
第六步: 查看分表數據
第七步: 查看總表數據
這樣就把表member中的數據分開了, 分成的表組為 tb_member為主表,tb_member1與tb_member2為分表.分表後,數據都是存放在分表裏,總表只是一個外殼,存取數據發生在一個一個的分表裏面。
對於merge表,需要註意的是
1. 每個子表的結構必須一致,主表和子表的結構需要一致,
2. 每個子表的索引在merge表中都會存在,所以在merge表中不能根據該索引進行唯一性檢索。
3. 子表需要是MyISAM引擎
4. REPLACE在merge表中不會工作
5. AUTO_INCREMENT 不會按照你所期望的方式工作
創建Mysql Merge表的參數 INSERT_METHOD有幾個參數 。
LAST 如果你執行insert 指令來操作merge表時,插入操作會把數據添加到最後一個子表中。
FIRST 同理,執行插入數據時會把數據添加到第一個子表中。
轉載請註明出處:[http://www.cnblogs.com/dennisit/p/3649931.html]
mysql--分表