1. 程式人生 > 其它 >MySQL 分表

MySQL 分表

一、先說一下為什麼要分表:
當一張的資料達到幾百萬時,你查詢一次所花的時間會變多,如果有聯合查詢的話,有可能會死在那兒了。分表的目的就在於此,減小資料庫的負擔,縮短查詢時間。

mysql執行一個sql的過程如下:
1、接收到sql;
2、把sql放到排隊佇列中;
3、執行sql;
4、返回執行結果。
在這個執行過程中最花時間在什麼地方呢?第一,是排隊等待的時間,第二,sql的執行時間。其實這二個是一回事,等待的同時,肯定有sql在執行。所以我們要縮短sql的執行時間。

mysql中有一種機制是表鎖定和行鎖定,為什麼要出現這種機制,是為了保證資料的完整性,我舉個例子來說吧,如果有二個sql都要修改同一張表的同一條資料,這個時候怎麼辦呢,是不是二個sql都可以同時修改這條資料呢?很顯然mysql對這種情況的處理是,一種是表鎖定(myisam儲存引擎),一個是行鎖定(innodb儲存引擎)。表鎖定表示你們都不能對這張表進行操作,必須等我對錶操作完才行。行鎖定也一樣,別的sql必須等我對這條資料操作完了,才能對這條資料進行操作。如果資料太多,一次執行的時間太長,等待的時間就越長,這也是我們為什麼要分表的原因。

二、分表的方案

1、叢集

1,做mysql叢集,有人會問mysql叢集,根分表有什麼關係嗎?雖然它不是實際意義上的分表,但是它啟到了分表的作用,做叢集的意義是什麼呢?為一個數據庫減輕負擔,說白了就是減少sql排隊佇列中的sql的數量,舉個例子:有10個sql請求,如果放在一個數據庫伺服器的排隊佇列中,他要等很長時間,如果把這10個sql請求,分配到5個數據庫伺服器的排隊佇列中,一個數據庫伺服器的佇列中只有2個,這樣等待時間是不是大大的縮短了呢?這已經很明顯了。所以我把它列到了分表的範圍以內,我做過一些mysql的叢集:

linux mysql proxy 的安裝,配置,以及讀寫分離
mysql replication 互為主從的安裝及配置,以及資料同步


優點:擴充套件性好,沒有多個分表後的複雜操作(php程式碼)
缺點:單個表的資料量還是沒有變,一次操作所花的時間還是那麼多,硬體開銷大。

2、分表

分表的2種方式:

講欄位拆分到不同表中,將原表中的string型別欄位拆分到其他表,能夠加快主表的查詢。

2.垂直分割就是按欄位分.
一個數據庫有3000W使用者記錄.包括欄位id,user,password,first_name,last_name,email,addr,等幾十欄位.使用者登入時需要user,password欄位,需要查詢user,password欄位比較慢,若是把它user,password單建立一表,速度會快.使用者的其它欄位獨立再建立一個表.這僅是一個例子.



把資料拆分到多個同樣結構的表中。

水平.就是按記錄分.一個數據庫有3000W使用者記錄.處理速度比較慢.這時可以把3000W.分成五份.每份都是600W.分別放在不同的機器上.

水平分表:

就是預先估計會出現大資料量並且訪問頻繁的表,將其分為若干個表,這種預估大差不差的,論壇裡面發表帖子的表,時間長了這張表肯定很大,幾十萬,幾百萬都有可能。 聊天室裡面資訊表,幾十個人在一起一聊一個晚上,時間長了,這張表的資料肯定很大。像這樣的情況很多。所以這種能預估出來的大資料量表,我們就事先分出個N個表,這個N是多少,根據實際情況而定。以聊天資訊表為例:

我事先建100個這樣的表,message_00,message_01,message_02……….message_98,message_99.然後根據使用者的ID來判斷這個使用者的聊天資訊放到哪張表裡面,可以用求餘的方式來獲得

3、實際應用中:

需要把垂直分表和水平分表結合起來使用,如果一個數據庫有3000w使用者的話,可以先考慮垂直拆,拆完之後在進行水平拆分。

就是先將其他欄位拆分到user_info表中,使用者主表只留下使用者id,密碼,使用者名稱等關鍵欄位。

之後在進行水平拆分,將使用者和使用者資訊表分為多個同樣結構的表。

思考:

水平分表怎麼保證插入的id的唯一? 【使用者id唯一】

答:可以新建一個id服務,把使用者的id儲存在資料庫或者redis中。