資料庫分表與分割槽
mysql分表的3種方法
一,先說一下為什麼要分表
當一張的資料達到幾百萬時,你查詢一次所花的時間會變多,如果有聯合查詢的話,我想有可能會死在那兒了。分表的目的就在於此,減小資料庫的負擔,縮短查詢時間。
根據個人經驗,mysql執行一個sql的過程如下:
1,接收到sql;2,把sql放到排隊佇列中 ;3,執行sql;4,返回執行結果。在這個執行過程中最花時間在什麼地方呢?第一,是排隊等待的時間,第二,sql的執行時間。其實這二個是一回事,等待的同時,肯定有sql在執行。所以我們要縮短sql的執行時間。
mysql中有一種機制是表鎖定和行鎖定,為什麼要出現這種機制,是為了保證資料的完整性,我舉個例子來說吧,如果有二個sql都要修改同一張表的同一條資料,這個時候怎麼辦呢,是不是二個sql都可以同時修改這條資料呢?很顯然mysql對這種情況的處理是,一種是表鎖定(myisam儲存引擎),一個是行鎖定(innodb儲存引擎)。表鎖定表示你們都不能對這張表進行操作,必須等我對錶操作完才行。行鎖定也一樣,別的sql必須等我對這條資料操作完了,才能對這條資料進行操作。如果資料太多,一次執行的時間太長,等待的時間就越長,這也是我們為什麼要分表的原因。
二,分表
1,做mysql叢集,例如:利用mysql cluster ,mysql proxy,mysql replication,drdb等等
有人會問mysql叢集,根分表有什麼關係嗎?雖然它不是實際意義上的分表,但是它啟到了分表的作用,做叢集的意義是什麼呢?為一個數據庫減輕負擔,說白了就是減少sql排隊佇列中的sql的數量,舉個例子:有10個sql請求,如果放在一個數據庫伺服器的排隊佇列中,他要等很長時間,如果把這10個sql請求,分配到5個數據庫伺服器的排隊佇列中,一個數據庫伺服器的佇列中只有2個,這樣等待時間是不是大大的縮短了呢?這已經很明顯了。所以我把它列到了分表的範圍以內,我做過一些mysql的叢集:
優點:擴充套件性好,沒有多個分表後的複雜操作(php程式碼)
缺點:單個表的資料量還是沒有變,一次操作所花的時間還是那麼多,硬體開銷大。
2,預先估計會出現大資料量並且訪問頻繁的表,將其分為若干個表
這種預估大差不差的,論壇裡面發表帖子的表,時間長了這張表肯定很大,幾十萬,幾百萬都有可能。 聊天室裡面資訊表,幾十個人在一起一聊一個晚上,時間長了,這張表的資料肯定很大。像這樣的情況很多。所以這種能預估出來的大資料量表,我們就事先分出個N個表,這個N是多少,根據實際情況而定。以聊天資訊表為例:
我事先建100個這樣的表,message_00,message_01,message_02..........message_98,message_99.然後根據使用者的ID來判斷這個使用者的聊天資訊放到哪張表裡面,你可以用hash的方式來獲得,可以用求餘的方式來獲得,方法很多,各人想各人的吧。下面用hash的方法來獲得表名:
<?php
function get_hash_table($table,$userid) {
$str = crc32($userid);
if($str<0){
$hash = "0".substr(abs($str), 0, 1);
}else{
$hash = substr($str, 0, 2);
}
return $table."_".$hash;
}
echo get_hash_table('message','user18991'); //結果為message_10
echo get_hash_table('message','user34523'); //結果為message_13
?>
說明一下,上面的這個方法,告訴我們user18991這個使用者的訊息都記錄在message_10這張表裡,user34523這個使用者的訊息都記錄在message_13這張表裡,讀取的時候,只要從各自的表中讀取就行了。
優點:避免一張表出現幾百萬條資料,縮短了一條sql的執行時間
缺點:當一種規則確定時,打破這條規則會很麻煩,上面的例子中我用的hash演算法是crc32,如果我現在不想用這個演算法了,改用md5後,會使同一個使用者的訊息被儲存到不同的表中,這樣資料亂套了。擴充套件性很差。
3,利用merge儲存引擎來實現分表
我覺得這種方法比較適合,那些沒有事先考慮,而已經出現了得,資料查詢慢的情況。這個時候如果要把已有的大資料量表分開比較痛苦,最痛苦的事就是改程式碼,因為程式裡面的sql語句已經寫好了,現在一張表要分成幾十張表,甚至上百張表,這樣sql語句是不是要重寫呢?舉個例子,我很喜歡舉子
mysql>show engines;的時候你會發現mrg_myisam其實就是merge。
mysql> CREATE TABLE IF NOT EXISTS `user1` (-> `id` int(11) NOT NULL AUTO_INCREMENT,
-> `name` varchar(50) DEFAULT NULL,
-> `sex` int(1) NOT NULL DEFAULT '0',
-> PRIMARY KEY (`id`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Query OK, 0 rows affected (0.05 sec)
mysql> CREATE TABLE IF NOT EXISTS `user2` (
-> `id` int(11) NOT NULL AUTO_INCREMENT,
-> `name` varchar(50) DEFAULT NULL,
-> `sex` int(1) NOT NULL DEFAULT '0',
-> PRIMARY KEY (`id`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO `user1` (`name`, `sex`) VALUES('張映', 0);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `user2` (`name`, `sex`) VALUES('tank', 1);
Query OK, 1 row affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `alluser` (
-> `id` int(11) NOT NULL AUTO_INCREMENT,
-> `name` varchar(50) DEFAULT NULL,
-> `sex` int(1) NOT NULL DEFAULT '0',
-> INDEX(id)
-> ) TYPE=MERGE UNION=(user1,user2) INSERT_METHOD=LAST AUTO_INCREMENT=1 ;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> select id,name,sex from alluser;
+----+--------+-----+
| id | name | sex |
+----+--------+-----+
| 1 | 張映 | 0 |
| 1 | tank | 1 |
+----+--------+-----+
2 rows in set (0.00 sec)
mysql> INSERT INTO `alluser` (`name`, `sex`) VALUES('tank2', 0);
Query OK, 1 row affected (0.00 sec)
mysql> select id,name,sex from user2
-> ;
+----+-------+-----+
| id | name | sex |
+----+-------+-----+
| 1 | tank | 1 |
| 2 | tank2 | 0 |
+----+-------+-----+
2 rows in set (0.00 sec)
從上面的操作中,我不知道你有沒有發現點什麼?假如我有一張使用者表user,有50W條資料,現在要拆成二張表user1和user2,每張表25W條資料,
INSERT INTO user1(user1.id,user1.name,user1.sex)SELECT (user.id,user.name,user.sex)FROM user where user.id <= 250000
INSERT INTO user2(user2.id,user2.name,user2.sex)SELECT (user.id,user.name,user.sex)FROM user where user.id > 250000
這樣我就成功的將一張user表,分成了二個表,這個時候有一個問題,程式碼中的sql語句怎麼辦,以前是一張表,現在變成二張表了,程式碼改動很大,這樣給程式設計師帶來了很大的工作量,有沒有好的辦法解決這一點呢?辦法是把以前的user表備份一下,然後刪除掉,上面的操作中我建立了一個alluser表,只把這個alluser表的表名改成user就行了。但是,不是所有的mysql操作都能用的
a,如果你使用 alter table 來把 merge 表變為其它表型別,到底層表的對映就被丟失了。取而代之的,來自底層 myisam 表的行被複制到已更換的表中,該表隨後被指定新型別。
b,網上看到一些說replace不起作用,我試了一下可以起作用的。暈一個先
- mysql> UPDATE alluser SET sex=REPLACE(sex, 0, 1) where id=2;
- Query OK, 1 row affected (0.00 sec)
- Rows matched: 1 Changed: 1 Warnings: 0
- mysql> select * from alluser;
- +----+--------+-----+
- | id | name | sex |
- +----+--------+-----+
- | 1 | 張映 | 0 |
- | 1 | tank | 1 |
- | 2 | tank2 | 1 |
- +----+--------+-----+
- 3 rows in set (0.00 sec)
c,一個 merge 表不能在整個表上維持 unique 約束。當你執行一個 insert,資料進入第一個或者最後一個 myisam 表(取決於 insert_method 選項的值)。mysql 確保唯一鍵值在那個 myisam 表裡保持唯一,但不是跨集合裡所有的表。
d,當你建立一個 merge 表之時,沒有檢查去確保底層表的存在以及有相同的機構。當 merge 表被使用之時,mysql 檢查每個被對映的表的記錄長度是否相等,但這並不十分可靠。如果你從不相似的 myisam 表建立一個 merge 表,你非常有可能撞見奇怪的問題。
好睏睡覺了,c和d在網上看到的,沒有測試,大家試一下吧。
優點:擴充套件性好,並且程式程式碼改動的不是很大
缺點:這種方法的效果比第二種要差一點
三,總結一下
上面提到的三種方法,我實際做過二種,第一種和第二種。第三種沒有做過,所以說的細一點。哈哈。做什麼事都有一個度,超過個度就過變得很差,不能一味的做資料庫伺服器叢集,硬體是要花錢買的,也不要一味的分表,分出來1000表,mysql的儲存歸根到底還以檔案的形勢存在硬碟上面,一張表對應三個檔案,1000個分表就是對應3000個檔案,這樣檢索起來也會變的很慢。我的建議是
方法1和方法2結合的方式來進行分表
方法1和方法3結合的方式來進行分表
http://blog.51yip.com/mysql/949.html
我的二個建議適合不同的情況,根據個人情況而定,我覺得會有很多人選擇方法1和方法3結合的方式
相關推薦
資料庫分表與分割槽
mysql分表的3種方法 一,先說一下為什麼要分表 當一張的資料達到幾百萬時,你查詢一次所花的時間會變多,如果有聯合查詢的話,我想有可能會死在那兒了。分表的目的就在於此,減小資料庫的負擔,縮短查詢時間。 根據個人經驗,mysql執行一個sql的過程如下: 1,接收到s
mysql分表與分割槽、主從複製
1.分割槽的工作原理 對使用者而言,分割槽表是一個獨立的邏輯表,但mysql底層將其分成了多個物理子表,每一個分割槽都是一個獨立的子檔案; 分割槽不需要改動原先的sql語句。 建立表時使用partition by子句定義每個分割槽存放的資料,執行查詢時,mysql優化器會過濾那些沒有我們
MySql分庫分表與分割槽的區別和思考
一.分分合合 說過很多次,不要拘泥於某一個技術的一點,技術是相通的。重要的是程式設計思想,思想是最重要的。當資料量大的時候,需要具有分的思想去細化粒度。當資料量太碎片的時候,需要具有合的思想來粗化粒度。 1.1 分 很多技術都運用了分的程式設計思想,這裡來舉幾個例子,這些都是分的思想 集中式服務發
MySql資料庫分表分割槽實踐
1. 背景 —— 公司物聯網專案 海量裝置通過物聯網服務接入雲端,裝置每30s上報一次自身資料(以下稱為動態資料)。 物聯網服務將裝置上報的資料轉發給資料處理閘道器,由資料入庫閘道器執行批量入庫操作插入資料庫。 專案大致技術架構如下圖: 2. 問題 接入的裝置數量較大時,上報的動態資料
MySQL的分表與分區
創建 alter 讀寫 created 例如 mysq 不能 eth art MySQL分表分區是解決大數據量導致MySQL性能低下的兩種方法。 什麽是MySQL分表 從表面意思上看,MySQL分表就是將一個表分成多個表,數據和數據結構都有可能會變。MySQL分表分為垂直分
六、資料庫之 表與表之間的關係
表1 foreign key 表2 則表1的多條記錄對應表2的一條記錄,即多對一 利用foreign key的原理我們可以製作兩張表的多對多,一對一關係 多對多: 表1的多條記錄可以對應表2的一條記錄 表2的多條記錄也可以對應表1的一條
記一次資料庫分表的初體驗!
業務前景 由於小編所在的公司是傳統型公司,而業務對接的確實像螞蟻貨運險這樣的大業務,從2017年中旬對接到公司的業務資料量大約一天150W左右資料,而去年的雙十一最高峰值則達到2000W一天的資料量!公司所入的資料量全部存在10多張不同業務的表中,而中途資料庫已經告警過幾次,顯然這樣
mysql資料庫分表時,使用mybatis動態設定表名
mybatis中傳遞引數一般使用#{},但是當引數是表名時#{}就會報錯。這是為啥呢? 這是因為#{ } 解析為一個 JDBC 預編譯語句(prepared statement)的引數標記符。 簡單來講:select * from user_#{tableVersion} 會被解析為
Java架構/一致性Hash演算法在資料庫分表中的實踐
最近有一個專案,其中某個功能單表資料在可預估的未來達到了億級,初步估算在90億左右。與同事詳細討論後,決定採用一致性Hash演算法來完成資料庫的自動擴容和資料遷移。整個程式細節由我同事完成,我只是將其理解併成文,供有相同問題的同行參考。 參看此文的兄弟,預設各位已經熟悉一致性hash
一致性Hash演算法在資料庫分表中的實踐
最近有一個專案,其中某個功能單表資料在可預估的未來達到了億級,初步估算在90億左右。與同事詳細討論後,決定採用一致性Hash演算法來完成資料庫的自動擴容和資料遷移。整個程式細節由我同事完成,我只是將其理解併成文,供有相同問題的同行參考。 參看此文的兄弟,預設各位已經熟悉一致性hash演算法了。此文僅僅闡述程式
Python 大資料庫備份阿里雲RDS資料庫分表匯出壓縮
思路:因為有的資料庫比較大,整體壓縮之後還是會有幾個G內容,既不方便下載也不方便恢復,然後就想到了對獨立的表分開進行備份。 1.連線阿里雲rds 2.建立資料夾,層級關係(資料庫名->日期->表名壓縮包) 3.迴圈需要備份的資料庫 4.從相應的資料庫查詢全
shell 備份資料庫分表備份
對資料庫分表備份。 #!/bin/sh # 定義資料庫連線引數 db_host=127.0.0.1 db_port=3306 db_username=root db_password=123456 #定義當前伺服器要備份的資料庫 db_name=(bajie beida
分表與分庫使用場景以及設計方式
一. 分表 場景:對於大型的網際網路應用來說,資料庫單表的記錄行數可能達到千萬級甚至是億級,並且資料庫面臨著極高的併發訪問。採用Master-Slave複製模式的MySQL架構, 只能夠對資料庫的讀進行擴充套件,而對資料庫的寫入操作還是集中在Master上,並
資料庫分表分庫
一、MySQL擴充套件具體的實現方式 隨著業務規模的不斷擴大,需要選擇合適的方案去應對資料規模的增長,以應對逐漸增長的訪問壓力和資料量。 關於資料庫的擴充套件主要包括:業務拆分、主從複製,資料庫分庫與分表。這篇文章主要講述資料庫分庫與分表 (1)業務拆分 在 大型網站應用之海量資料和
mysql學習【第6篇】:資料庫之表與表之間的關係 資料庫之 表與表之間的關係
資料庫之 表與表之間的關係 表1 foreign key 表2 則表1的多條記錄對應表2的一條記錄,即多對一
MySQL分表技術&分割槽技術
一、分表技術 1、說明 說明:當一張表資料巨大時,不管如何優化,查詢也會相當慢 解決:1-增加查詢快取,2-使用分表技術 2、實現分表的方法 水平分表:手動建立多張表,通過PHP演算法判斷實現讀寫 垂直分表:將表字段拆分到其他表中 3、水平分表 水平分表圖示:
Mysql關於分庫、分表、分割槽的具體介紹
1、分表 分表是將一個大表按照一定的規則分解成多張具有獨立儲存空間的實體表,我們可以稱為子表,每個表都對應三個檔案,MYD資料檔案,.MYI索引檔案,.frm表結構檔案。這些子表可以分佈在同一塊磁碟上,也可以在不同的機器上。app讀寫的時候根據事先定義好的規則得到對應的子表
MySQL分表、分割槽
主從複製 - 讀寫分離要解決的是資料庫併發訪問壓力; 分表和分割槽解決的是單表資料量大時的SQL效能壓力,另外分表也能一定程度上提高併發; 1. 什麼是分表、分割槽?分表和分割槽是不同層次的概念: 分表: 分表是開發人員的物理設計,目的是:在單表有大資料量的情況下保證SQL執行效能,也能提高併發。 我
大資料高併發之-Mysql分表與分庫使用場景以及設計方式
場景:對於大型的網際網路應用來說,資料庫單表的記錄行數可能達到千萬級甚至是億級,並且資料庫面臨著極高的併發訪問。採用Master-Slave複製模式的MySQL架構, 只能夠對資料庫的讀進行擴充套件,而
資料庫設計(表與表之間的3種關係)
表與表之間一般存在三種關係,即一對一,一對多,多對多關係。 下面分別就三種關係講解資料庫相關設計的思路和思考過程; (1)一對一關係 例如,下面的一張表,儲存了人的相關資訊,有男有女,要求查處所有的夫妻。 sql程式碼: CREATE TABLE