国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 數(shù)據(jù)庫(kù) > MySQL > 正文

mysql分表幾種方法總結(jié)

2024-07-24 12:38:03
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

分表對(duì)于中小型網(wǎng)站來(lái)說(shuō)幾乎不會(huì)用到,但是在大型級(jí)數(shù)據(jù)來(lái)說(shuō)mysql分表是常見(jiàn)的事情了,下面我來(lái)介紹幾種常用的mysql分表方法,希望對(duì)大家有所幫助.

分表

1,做mysql集群,例如,利用mysql cluster,mysql proxy,mysql replication,drdb等等.

有人會(huì)問(wèn)mysql集群,根分表有什么關(guān)系嗎?雖然它不是實(shí)際意義上的分表,但是它啟到了分表的作用,做集群的意義是什么呢?為一個(gè)數(shù)據(jù)庫(kù)減輕負(fù)擔(dān),說(shuō)白了就是減少sql排隊(duì)隊(duì)列中的sql的數(shù)量,舉個(gè)例子:有10個(gè)sql請(qǐng)求,如果放在一個(gè)數(shù)據(jù)庫(kù)服務(wù)器的排隊(duì)隊(duì)列中,他要等很長(zhǎng)時(shí)間,如果把這10個(gè)sql請(qǐng)求,分配到5個(gè)數(shù)據(jù)庫(kù)服務(wù)器的排隊(duì)隊(duì)列中,一個(gè)數(shù)據(jù)庫(kù)服務(wù)器的隊(duì)列中只有2個(gè),這樣等待時(shí)間是不是大大的縮短了呢?這已經(jīng)很明顯了。所以我把它列到了分表的范圍以內(nèi),我做過(guò)一些mysql的集群:

linux mysql proxy 的安裝,配置,以及讀寫分離

mysql replication 互為主從的安裝及配置,以及數(shù)據(jù)同步

優(yōu)點(diǎn):擴(kuò)展性好,沒(méi)有多個(gè)分表后的復(fù)雜操作(php代碼)

缺點(diǎn):單個(gè)表的數(shù)據(jù)量還是沒(méi)有變,一次操作所花的時(shí)間還是那么多,硬件開(kāi)銷大。

2,預(yù)先估計(jì)會(huì)出現(xiàn)大數(shù)據(jù)量并且訪問(wèn)頻繁的表,將其分為若干個(gè)表

這種預(yù)估大差不差的,論壇里面發(fā)表帖子的表,時(shí)間長(zhǎng)了這張表肯定很大,幾十萬(wàn),幾百萬(wàn)都有可能。 聊天室里面信息表,幾十個(gè)人在一起一聊一個(gè)晚上,時(shí)間長(zhǎng)了,這張表的數(shù)據(jù)肯定很大。像這樣的情況很多。所以這種能預(yù)估出來(lái)的大數(shù)據(jù)量表,我們就事先分出個(gè)N個(gè)表,這個(gè)N是多少,根據(jù)實(shí)際情況而定。以聊天信息表為例:

我事先建100個(gè)這樣的表,message_00,message_01,message_02……….message_98,message_99.然后根據(jù)用戶的ID來(lái)判斷這個(gè)用戶的聊天信息放到哪張表里面,你可以用hash的方式來(lái)獲得,可以用求余的方式來(lái)獲得,方法很多,各人想各人的吧。下面用hash的方法來(lái)獲得表名:

查看復(fù)制打印?代碼如下:

  1. <?php   
  2. function get_hash_table($table,$userid) {   
  3.  $str = crc32($userid);   
  4.  if($str<0){   
  5.  $hash = "0".substr(abs($str), 0, 1);   
  6.  }else{   
  7.  $hash = substr($str, 0, 2);   
  8.  }  //Vevb.com 
  9.  
  10.  return $table."_".$hash;   
  11. }   
  12.  
  13. echo get_hash_table('message','user18991');     //結(jié)果為message_10   
  14. echo get_hash_table('message','user34523');    //結(jié)果為message_13   
  15. ?> 

說(shuō)明一下,上面的這個(gè)方法,告訴我們user18991這個(gè)用戶的消息都記錄在message_10這張表里,user34523這個(gè)用戶的消息都記錄在message_13這張表里,讀取的時(shí)候,只要從各自的表中讀取就行了。

優(yōu)點(diǎn):避免一張表出現(xiàn)幾百萬(wàn)條數(shù)據(jù),縮短了一條sql的執(zhí)行時(shí)間

缺點(diǎn):當(dāng)一種規(guī)則確定時(shí),打破這條規(guī)則會(huì)很麻煩,上面的例子中我用的hash算法是crc32,如果我現(xiàn)在不想用這個(gè)算法了,改用md5后,會(huì)使同一個(gè)用戶的消息被存儲(chǔ)到不同的表中,這樣數(shù)據(jù)亂套了。擴(kuò)展性很差。

3,利用merge存儲(chǔ)引擎來(lái)實(shí)現(xiàn)分表

我覺(jué)得這種方法比較適合,那些沒(méi)有事先考慮,而已經(jīng)出現(xiàn)了得,數(shù)據(jù)查詢慢的情況。這個(gè)時(shí)候如果要把已有的大數(shù)據(jù)量表分開(kāi)比較痛苦,最痛苦的事就是改代碼,因?yàn)槌绦蚶锩娴膕ql語(yǔ)句已經(jīng)寫好了,現(xiàn)在一張表要分成幾十張表,甚至上百?gòu)埍恚@樣sql語(yǔ)句是不是要重寫呢?舉個(gè)例子,我很喜歡舉子

mysql>show engines;的時(shí)候你會(huì)發(fā)現(xiàn)mrg_myisam其實(shí)就是merge,代碼如下:

  1. mysql> CREATE TABLE IF NOT EXISTS `user1` (   
  2.  ->   `id` int(11) NOT NULL AUTO_INCREMENT,   
  3.  ->   `namevarchar(50) DEFAULT NULL,   
  4.  ->   `sex` int(1) NOT NULL DEFAULT '0',   
  5.  ->   PRIMARY KEY (`id`)   
  6.  -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;   
  7. Query OK, 0 rows affected (0.05 sec)   
  8.  
  9. mysql> CREATE TABLE IF NOT EXISTS `user2` (   
  10.  ->   `id` int(11) NOT NULL AUTO_INCREMENT,   
  11.  ->   `namevarchar(50) DEFAULT NULL,   
  12.  ->   `sex` int(1) NOT NULL DEFAULT '0',   
  13.  ->   PRIMARY KEY (`id`)   
  14.  -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;   
  15. Query OK, 0 rows affected (0.01 sec)   
  16.  
  17. mysql> INSERT INTO `user1` (`name`, `sex`) VALUES('張映', 0);   
  18. Query OK, 1 row affected (0.00 sec)   
  19.  
  20. mysql> INSERT INTO `user2` (`name`, `sex`) VALUES('tank', 1);   
  21. Query OK, 1 row affected (0.00 sec)   
  22.  
  23. mysql> CREATE TABLE IF NOT EXISTS `alluser` (   
  24.  ->   `id` int(11) NOT NULL AUTO_INCREMENT,   
  25.  ->   `namevarchar(50) DEFAULT NULL,   
  26.  ->   `sex` int(1) NOT NULL DEFAULT '0',   
  27.  ->   INDEX(id)   
  28.  -> ) TYPE=MERGE UNION=(user1,user2) INSERT_METHOD=LAST AUTO_INCREMENT=1 ;   
  29. Query OK, 0 rows affected, 1 warning (0.00 sec)   
  30.  
  31. mysql> select id,name,sex from alluser;   
  32. +----+--------+-----+   
  33. | id | name   | sex |   
  34. +----+--------+-----+   
  35. |  1 | 張映 |   0 |   
  36. |  1 | tank   |   1 |   
  37. +----+--------+-----+   
  38. rows in set (0.00 sec)   
  39.  
  40. mysql> INSERT INTO `alluser` (`name`, `sex`) VALUES('tank2', 0);   
  41. Query OK, 1 row affected (0.00 sec)   
  42.  
  43. mysql> select id,name,sex from user2   
  44.  -> ;   
  45. +----+-------+-----+   
  46. | id | name  | sex |   
  47. +----+-------+-----+   
  48. |  1 | tank  |   1 |   
  49. |  2 | tank2 |   0 |   
  50. +----+-------+-----+   

2 rows in set (0.00 sec)從上面的操作中,我不知道你有沒(méi)有發(fā)現(xiàn)點(diǎn)什么?假如我有一張用戶表user,有50W條數(shù)據(jù),現(xiàn)在要拆成二張表user1和user2,每張表25W條數(shù)據(jù),代碼如下:

  1. INSERT INTO user1(user1.id,user1.name,user1.sex)SELECT (user.id,user.name,user.sex)FROM user where user.id <= 250000 
  2. INSERT INTO user2(user2.id,user2.name,user2.sex)SELECT (user.id,user.name,user.sex)FROM user where user.id > 250000 

這樣我就成功的將一張user表,分成了二個(gè)表,這個(gè)時(shí)候有一個(gè)問(wèn)題,代碼中的sql語(yǔ)句怎么辦,以前是一張表,現(xiàn)在變成二張表了,代碼改動(dòng)很大,這樣給程序員帶來(lái)了很大的工作量,有沒(méi)有好的辦法解決這一點(diǎn)呢?辦法是把以前的user表備份一下,然后刪除掉,上面的操作中我建立了一個(gè)alluser表,只把這個(gè)alluser表的表名改成user就行了。但是,不是所有的mysql操作都能用的

a,如果你使用 alter table 來(lái)把 merge 表變?yōu)槠渌眍愋停降讓颖淼挠成渚捅粊G失了。取而代之的,來(lái)自底層 myisam 表的行被復(fù)制到已更換的表中,該表隨后被指定新類型。

b,網(wǎng)上看到一些說(shuō)replace不起作用,我試了一下可以起作用的,暈一個(gè)先,代碼如下:

  1. mysql> UPDATE alluser SET sex=REPLACE(sex, 0, 1) where id=2;   
  2. Query OK, 1 row affected (0.00 sec)   
  3. Rows matched: 1  Changed: 1  Warnings: 0   
  4.  
  5. mysql> select * from alluser;   
  6. +----+--------+-----+   
  7. | id | name   | sex |   
  8. +----+--------+-----+   
  9. |  1 | 張映 |   0 |   
  10. |  1 | tank   |   1 |   
  11. |  2 | tank2  |   1 |   
  12. +----+--------+-----+   

3 rows in set (0.00 sec)c,一個(gè) merge 表不能在整個(gè)表上維持 unique 約束。當(dāng)你執(zhí)行一個(gè) insert,數(shù)據(jù)進(jìn)入第一個(gè)或者最后一個(gè) myisam 表,取決于 insert_method 選項(xiàng)的值,mysql 確保唯一鍵值在那個(gè) myisam 表里保持唯一,但不是跨集合里所有的表.

d,當(dāng)你創(chuàng)建一個(gè) merge 表之時(shí),沒(méi)有檢查去確保底層表的存在以及有相同的機(jī)構(gòu)。當(dāng) merge 表被使用之時(shí),mysql 檢查每個(gè)被映射的表的記錄長(zhǎng)度是否相等,但這并不十分可靠。如果你從不相似的 myisam 表創(chuàng)建一個(gè) merge 表,你非常有可能撞見(jiàn)奇怪的問(wèn)題。

好困睡覺(jué)了,c和d在網(wǎng)上看到的,沒(méi)有測(cè)試,大家試一下吧。

優(yōu)點(diǎn):擴(kuò)展性好,并且程序代碼改動(dòng)的不是很大

缺點(diǎn):這種方法的效果比第二種要差一點(diǎn)

三,總結(jié)一下

上面提到的三種方法,我實(shí)際做過(guò)二種,第一種和第二種。第三種沒(méi)有做過(guò),所以說(shuō)的細(xì)一點(diǎn)。哈哈。做什么事都有一個(gè)度,超過(guò)個(gè)度就過(guò)變得很差,不能一味的做數(shù)據(jù)庫(kù)服務(wù)器集群,硬件是要花錢買的,也不要一味的分表,分出來(lái)1000表,mysql的存儲(chǔ)歸根到底還以文件的形勢(shì)存在硬盤上面,一張表對(duì)應(yīng)三個(gè)文件,1000個(gè)分表就是對(duì)應(yīng)3000個(gè)文件,這樣檢索起來(lái)也會(huì)變的很慢,我的建議是:

方法1和方法2結(jié)合的方式來(lái)進(jìn)行分表

方法1和方法3結(jié)合的方式來(lái)進(jìn)行分表

我的二個(gè)建議適合不同的情況,根據(jù)個(gè)人情況而定,我覺(jué)得會(huì)有很多人選擇方法1和方法3結(jié)合的方式.

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 繁昌县| 山丹县| 天津市| 兴国县| 临颍县| 阳泉市| 普定县| 读书| 龙南县| 虹口区| 明溪县| 宣城市| 宜兴市| 浑源县| 固安县| 庆城县| 百色市| 佛山市| 沅陵县| 新昌县| 舒兰市| 高台县| 临邑县| 阿巴嘎旗| 泾川县| 五常市| 桃江县| 伊金霍洛旗| 成安县| 孟津县| 县级市| 长春市| 泸州市| 甘洛县| 大兴区| 宝清县| 尚志市| 岢岚县| 房产| 阿拉尔市| 恭城|