mysql 數據庫分表小實例

項目開發中,咱們的數據庫數據愈來愈大,隨之而來的是單個表中數據太多。以致於查詢書讀變慢,並且因爲表的鎖機制致使應用操做也搜到嚴重影響,出現了數據庫性能瓶頸。mysql

當出現這種狀況時,咱們能夠考慮分表,即將單個數據庫表進行拆分,拆分紅多個數據表,而後用戶訪問的時候,根據必定的算法,讓用戶訪問不一樣的表,這樣數據分散到多個數據表中,減小了單個數據表的訪問壓力。提高了數據庫訪問性能。redis

咱們能夠進行簡單的設想:如今有一個表products存儲產品信息,如今有100萬用戶在線訪問,就要進行至少100萬次請求,如今咱們若是將它分紅100個表即products0~~products99,那麼利用必定的算法咱們就分擔了單個表的訪問壓力,每一個表只有1萬個請求(固然,這是理想狀況下!)算法

實現mysql 分表的關鍵在於:設計良好的算法來肯定"何時狀況下訪問什麼(哪一個)表"。sql

下面咱們先來實現一個簡單的mysql分表演示:這裏使用MERGE分表法數據庫

1,建立一個完整表存儲着全部的成員信息緩存

 

create table member(
id bigint auto_increment primary key,
name varchar(20),
sex tinyint not null default '0'
)engine=myisam default charset=utf8 auto_increment=1;

 

加入點數據:post

  insert into member(id,name,sex) values (1,'jacson','0');性能

  insert into member(name,sex) select name,sex from member;設計

第二條語句多執行幾回就有了不少數據。blog

2,下面咱們進行分表:這裏咱們分兩個表tb_member1,tb_member2

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 ; 

DROP table IF EXISTS tb_member2;
create table tb_member2(
    id bigint primary key auto_increment ,
    name varchar(20),
    sex tinyint not null default '0'
)ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 
//建立tb_member2也能夠用下面的語句  create table tb_member2 like tb_member1;

 

 3.建立主表tb_member

DROP table IF EXISTS tb_member;
create table tb_member(
    id bigint primary key auto_increment ,
    name varchar(20),
    sex tinyint not null default '0'
)ENGINE=MERGE UNION=(tb_member1,tb_member2) INSERT_METHOD=LAST CHARSET=utf8 AUTO_INCREMENT=1 ;

 

4,接下來,咱們把數據分到兩個分表中去:

insert into tb_member1(id,name,sex) select id,name,sex from member where id%2=0;

insert into tb_member2(id,name,sex) select id,name,sex from member where id%2=1;

查看一下主表的數據:select * from tb_member;

 

注意:總表只是一個外殼,存取數據發生在一個一個的分表裏面。

ps:建立主表時可能會出現下面的錯誤:

ERROR 1168 (HY000): Unable to open underlying table which is differently defined
or of non-MyISAM type or doesn't exist

若遇到上面這種錯誤,通常從兩方面來排查:(從這兩方面通常能夠解決這個問題,本人也遇到了。)

  1,查看上面的分表數據庫引擎是否是MyISAM.

  2,查看分表與指標的字段定義是否一致。

 

 

分表的大概過程和步驟就是這樣的,下面咱們來看看分表的算法實現:

假設如今有一個應用系統可能會有100億的用戶量,另一個表通常存儲量在不超過100萬的時候基本能保持良好性能,計算下來,咱們須要1萬張表,即分表爲1萬個表。

咱們能夠設計成:user_0~user_9999

在用戶表裏面咱們有惟一的標示是用戶id,咱們尅設計一個小算法來實現用戶id與訪問表名的對應:

function getTable($id)

{

   return 'user_'.sprintf('%d',($id >>20));

}

解釋一下:($id >> 20)表示將向右移位20位,(向右移動一位標示減小一半),printf('%d',$data)標示將數據按照十進制輸出。

               即id爲1~1048575(2的20次冪-1)時均訪問user_0,1048576~2097152時訪問user_1,以此類推.....

那麼問題來了,若是用戶更多怎麼辦,如今須要一個可擴展的方法:

function getTable($id,$bit,$seed){
   return 'user_'.sprintf('%0{$bit}d',($id >> $seed));
}
其中:$id爲用戶id,$bit標示表後綴的位數,$seed表示要移位的位數即:單個表能存儲的記錄條數。
這樣就能夠任意分表了。
 
 
總結:
     其實上面咱們介紹的是水平分表的實施方法,還存在另外一種方法叫作:垂直分表
     垂直分表:
      舉例說明,在一個博客系統中,文章標題,做者,分類,建立時間等,是變化頻率慢,查詢次數多,並且最好有很好的實時性的數據,咱們把它叫作冷數據。     而博客的瀏覽量,回覆數等,相似的統計信息,或者別的變化頻率比較高的數據,咱們把它叫作活躍數據。        咱們進行縱向分表後:       1,存儲引擎的使用不一樣,冷數據使用MyIsam 能夠有更好的查詢數據。活躍數據,可使用Innodb ,能夠有更好的更新速度。       2,對冷數據進行更多的從庫配置,由於更多的操做是查詢,這樣來加快查詢速度。對熱數據,能夠相對有更多的主庫的橫向分表處理。       3,對於一些特殊的活躍數據,也能夠考慮使用memcache ,redis之類的緩存,等累計到必定量再去更新數據庫.
相關文章
相關標籤/搜索