一:業務背景mysql
二:第一種業務水平拆分方案sql
三:第二種業務水平拆分方案bash
1.1因爲業務量的急劇增長,某張表的數據愈來愈大,如今假設的狀況爲某家公司的P2P網站,因爲前期宣傳比較好,在近三個月的時間裏業務量急劇增長,使得流水記錄表(trade)的數據量變的愈來愈大,已經超過300萬行記錄,預計年內流水錶的記錄可能會超過1000萬行,這個時候就須要考慮作表的水平拆分了ide
1.2 假設隨着業務量的增長,用戶量也增長了,由之前的幾千個用戶上升到100萬,也想對其進行水平拆分函數
2.1假設年內達到1000萬行記錄,再加上後續的考慮,暫且把流水錶(trade)拆分爲10張表,分別爲trade_0, trade_1, trade_2, trade_3... , trade_10網站
2.2流水錶中的字段假設以下字段ui
serial_number流水號 user_ID用戶ID request_message請求信息spa
2.3由於獲取流水是根據user_id(用戶ID)來獲取本身的流水狀況的,因此這裏以user_id來作分表3d
2.4 user_id%10用user_id模上10,等於幾就把等於這個user_id的記錄插入到trade_x中(x等於0到10)orm
2.5具體步驟
2.5.1先查看一下當前trade表中有多少條記錄,以便最後拆分完成之後覈對記錄是否丟失
2.5.2把user_id%10=0的記錄插入到trade_0,trade_1...trade_9表中
2.5.3把trade_0...trade_10表的記錄加起來,看是不是trade表的總記錄數
2.5.4以上是把已有的數據拆分紅多張表了,那麼查詢和插入如何操做呢?由於流水是和用戶的操做相關的,因此查詢和插入的時候,可使用拼接字符串的方式進行插入數據,例如上面的拆分方法就能夠這樣拼接
int suffix = user_id%10; String table_name = "trade_" + suffix; INSERT INTO table_name(...) values(...); 或者 SELECT * FROM table_name WHERE ...;
2.5.5總結,因爲以上拆分的表是根據已有的用戶ID進行拆分的,先有用戶,再有流水記錄,因此這種業務作拆分是比較容易的
3.1因爲用戶量的增加,對用戶表也要作數據拆分,拆分方案和以上相同,拆分爲user_main_0...user_main_5
3.2如今的問題是,用戶插入的時候,咱們不知道用戶ID是多少,也就意味着不知道應該往user_main_0...user_main_5那張表中插入數據
3.3爲了解決以上問題咱們能夠先執行一下SQL語句
mysql> SELECT AUTO_INCREMENT FROMinformation_schema.TABLES WHERE TABLE_NAME='user_main';
它返回的是當前表的下一個自增加ID的值
3.4經過以上SQL語句已經獲得了當前user_main表下一個ID值,下面建立user_main_uuid表
mysql> CREATE TABLEuser_main_uuid(user_main_next_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT);
3.5而後把「3.3 SQL語句」返回的值插入到user_main_uuid中
3.6那麼用戶註冊的時候,提交用戶填寫的信息,進入到controll的時候,校驗完用戶信息之後,首先先查user_main_uuid表的user_mian_next_id字段返回的值,而後根據這個值%5,等於幾,就給user_main_x中插入
3.7還有一個問題,用戶註冊完成以後,應該把user_main_next_id的值自動加1,不然,下個用戶註冊的時候ID會重複致使不能成功插入數據,因此在把數據成功插入到對應的user_main_x表中之後,再執行如下SQL語句
mysql> INSERT INTO user_main_uuidVALUES(NULL);
因爲插入一條記錄的方式來使ID自增的,因此「3.6」中應該獲取的是user_mian_next_id字段的最大值MAX(user_mian_next_id)
3.8除了以上更新user_mian_next_id的值之外,還能夠是如下方式
這樣user_main_uuid表中就永遠只有一條記錄,就不用使用MAX()函數了