一般下載的源碼都帶了MySQL數據庫的,做個真正意義上的網站沒數據庫肯定不行。 數據庫主要存放用戶信息(註冊用戶名密碼,分組,等級等),配置信息(管理權限配置,模板配置等),內容鏈接(html ,圖片,聲音,視頻等等的路徑)。那mysql數據庫爲什麼要分表和分區?
爲什麼要分表和分區?
我們的數據庫數據越來越大,隨之而來的是單個表中數據太多。以至於查詢書讀變慢,而且
由於表的鎖機制導致應用操作也搜到嚴重影響,出現了數據庫性能瓶頸。
mysql 中有一種機制是表鎖定和行鎖定,是爲了保證數據的完整性。表鎖定表示你們都不能
對這張表進行操作,必須等我對錶操作完纔行。行鎖定也一樣,別的 sql 必須等我對這條數
據操作完了,才能對這條數據進行操作。當出現這種情況時,我們可以考慮分表或分區。
1、分表
什麼是分表?
分表是將一個大表按照一定的規則分解成多張具有獨立存儲空間的實體表,每個表都對應三
個文件,MYD 數據文件,.MYI 索引文件,.frm 表結構文件。這些表可以分佈在同一塊磁盤
上,也可以在不同的機器上。app 讀寫的時候根據事先定義好的規則得到對應的表名,然後
去操作它。
將單個數據庫表進行拆分,拆分成多個數據表,然後用戶訪問的時候,根據一定的算法(如
用 hash 的方式,也可以用求餘(取模)的方式),讓用戶訪問不同的表,這樣數據分散到多
個數據表中,減少了單個數據表的訪問壓力。提升了數據庫訪問性能。分表的目的就在於此,
減小數據庫的負擔,縮短查詢時間。
Mysql 分表分爲垂直切分和水平切分
垂直切分是指數據表列的拆分,把一張列比較多的表拆分爲多張表
通常我們按以下原則進行垂直拆分:
把不常用的字段單獨放在一張表;
把 text,blob(binary large object,二進制大對象)等大字段拆分出來放在附表中;
經常組合查詢的列放在一張表中;
垂直拆分更多時候就應該在數據表設計之初就執行的步驟,然後查詢的時候用 jion 關鍵起來
即可。
水平拆分是指數據錶行的拆分,把一張的表的數據拆成多張表來存放。
水平拆分原則
通常情況下,我們使用 hash、取模等方式來進行表的拆分
比如一張有 400W 的用戶表 users,爲提高其查詢效率我們把其分成 4 張表 users1,users2,
users3,users4
通過用 ID 取模的方法把數據分散到四張表內 Id%4= [0,1,2,3]
然後查詢,更新,刪除也是通過取模的方法來查詢
部分業務邏輯也可以通過地區,年份等字段來進行歸檔拆分;
進行拆分後的表,這時我們就要約束用戶查詢行爲。比如我們是按年來進行拆分的,這個時
候在頁面設計上就約束用戶必須要先選擇年,然後才能進行查詢。
分表的幾種方式:
1)mysql 集羣
它並不是分表,但起到了和分表相同的作用。集羣可分擔數據庫的操作次數,將任務分擔到
多臺數據庫上。集羣可以讀寫分離,減少讀寫壓力。從而提升數據庫性能。
2)預先估計會出現大數據量並且訪問頻繁的表,將其分爲若干個表
根據一定的算法(如用 hash 的方式,也可以用求餘(取模)的方式)讓用戶訪問不同的表。
例如論壇裏面發表帖子的表,時間長了這張表肯定很大,幾十萬,幾百萬都有可能。聊天室裏面信息表,幾十個人在一起一聊一個晚上,時間長了,這張表的數據肯定很大。像這樣的
情況很多。所以這種能預估出來的大數據量表,我們就事先分出個 N 個表,這個 N 是多少,
根據實際情況而定。以聊天信息表爲例:我們事先建 100 個這樣的表,
message_00,message_01,message_02..........message_98,message_99.然後根據用戶的 ID 來判
斷這個用戶的聊天信息放到哪張表裏面,可以用 hash 的方式來獲得,也可以用求餘的方式
來獲得,方法很多。
或者可以設計每張表容納的數據量是 N 條,那麼如何判斷某張表的數據是否容量已滿呢?
可以在程序段對於要新增數據的表,在插入前先做統計表記錄數量的操作,當
就直接插入,當已經到達閥值,可以在程序段新創建數據庫表(或者已經事先創建好),再
執行插入操作)。
3)利用 merge 存儲引擎來實現分表
如果要把已有的大數據量表分開比較痛苦,最痛苦的事就是改代碼,因爲程序裏面的 sql 語
句已經寫好了,用 merge 存儲引擎來實現分表, 這種方法比較適合。
merge 分表,分爲主表和子表,主表類似於一個殼子,邏輯上封裝了子表,實際上數據都是
存儲在子表中的。
我們可以通過主表插入和查詢數據,如果清楚分表規律,也可以直接操作子表。
下面我們來實現一個簡單的利用 merge 存儲引擎來實現分表的演示:
創建一個完整表存儲着所有的成員信息(表名爲 member)
加入點數據:
第二條語句多執行幾次就有了很多數據:
下面我們進行分表,這裏我們把 member 分兩個表 tb_member1,tb_member2
創建主表 tb_member
注:INSERT_METHOD,此參數 INSERT_METHOD = NO 表示該表不能做任何寫入操作只作爲查
詢使用,INSERT_METHOD = LAST 表示插入到最後的一張表裏面。INSERT_METHOD = first 表示
插入到第一張表裏面。
查看一下 tb_member 表的結構:
注:查看子表與主表的字段定義要一致
接下來,我們把數據分到兩個分表中去:
查看兩個子表的數據:
查看一下主表的數據:
注意:總表只是一個外殼,存取數據發生在一個一個的子表裏面。
注意:每個子表都有自已獨立的相關表文件,而主表只是一個殼,並沒有完整的相關表文件。