原文連結:http://www.jianshu.com/p/89311703b320
傳統的分庫分表
傳統的分庫分表都是通過應用層邏輯實作的,對于資料庫層面來說,都是普通的表和庫。
分庫
分庫的原因
首先,在單台資料庫伺服器性能足夠的情況下,分庫對于資料庫性能是沒有影響的。在資料庫存儲上,database隻起到一個namespace的作用。database中的表檔案存儲在一個以database名命名的檔案夾中。比如下面的employees資料庫:
mysql> show tables in employees;
+---------------------+
| Tables_in_employees |
+---------------------+
| departments |
| dept_emp |
| dept_manager |
| employees |
| salaries |
| titles |
+---------------------+
在作業系統中看是這樣的:
ls /usr/local/var/mysql/employees
db.opt dept_emp.frm dept_manager.ibd salaries.frm titles.ibd
departments.frm dept_emp.ibd employees.frm salaries.ibd
departments.ibd dept_manager.frm employees.ibd titles.frm
database不是檔案,隻起到namespace的作用,是以MySQL對database大小當然也是沒有限制的,而且對裡面的表數量也沒有限制
是以,為什麼要分庫呢?
答案是為了解決單台伺服器的性能問題,當單台資料庫伺服器無法支撐目前的資料量時,就需要根據業務邏輯緊密程度把表分成幾撮,分别放在不同的資料庫伺服器中以降低單台伺服器的負載。
分庫一般考慮的是垂直切分,除非在垂直切分後,資料量仍然多到單台伺服器無法負載,才繼續水準切分。
比如一個論壇系統的資料庫因目前伺服器性能無法滿足需要進行分庫。先垂直切分,按業務邏輯把使用者相關資料表比如使用者資訊、積分、使用者間私信等放入user資料庫;論壇相關資料表比如闆塊,文章,回複等放入forum資料庫,兩個資料庫放在不同伺服器上。
拆分後表往往不可能完全無關聯,比如文章中的發帖人、回複人這些資訊都在user資料庫中。未拆分前可能一次聯表查詢就能擷取目前文章的回複、發帖人、回複人等所有資訊,拆分後因為跨資料庫無法聯表查詢,隻能多次查詢獲得最終資料。
是以總結起來,分庫的目的是降低單台伺服器負載,切分原則是根據業務緊密程度拆分,缺點是跨資料庫無法聯表查詢。
分表
分表的原因
當資料量超大的時候,B-Tree索引就無法起作用了。除非是索引覆寫查詢,否則資料庫伺服器需要根據索引掃描的結果回表,查詢所有符合條件的記錄,如果資料量巨大,這将産生大量随機I/O,随之,資料庫的響應時間将大到不可接受的程度。另外,索引維護(磁盤空間、I/O操作)的代價也非常高。
垂直分表
原因:
1.根據MySQL索引實作原理及相關優化政策的内容我們知道Innodb主索引葉子節點存儲着目前行的所有資訊,是以減少字段可使記憶體加載更多行資料,有利于查詢。
2.受限于作業系統中的檔案大小限制。
切分原則:
把不常用或業務邏輯不緊密或存儲内容比較多的字段分到新的表中可使表存儲更多資料。。
水準分表
原因:
1.随着資料量的增大,table行數巨大,查詢的效率越來越低。
2.同樣受限于作業系統中的檔案大小限制,資料量不能無限增加,當到達一定容量時,需要水準切分以降低單表(檔案)的大小。
切分原則: 增量區間或散列或其他業務邏輯。
使用哪種切分方法要根據實際業務邏輯判斷。
比如對表的通路多是近期産生的新資料,曆史資料通路較少,可以考慮根據時間增量把資料按照一定時間段(比如每年)切分。
如果對表的通路較均勻,沒有明顯的熱點區域,則可以考慮用範圍(比如每500w一個表)或普通Hash或一緻性Hash來切分。
全局主鍵問題:
原本依賴資料庫生成主鍵(比如自增)的表在拆分後需要自己實作主鍵的生成,因為一般拆分規則是建立在主鍵上的,是以在插入新資料時需要确定主鍵後才能找到存儲的表。
實際應用中也已經有了比較成熟的方案。比如對于自增列做主鍵的表,flickr的全局主鍵生成方案很好的解決了性能和單點問題,具體實作原理可以參考這個文章。除此之外,還有類似于uuid的全局主鍵生成方案,比如達達參考的Instagram的ID生成器。
一緻性Hash:
使用一緻性Hash切分比普通的Hash切分可擴充性更強,可以實作拆分表的添加和删除。一緻性Hash的具體原理可以參考這個文章,如果拆分後的表存儲在不同伺服器節點上,可以跟文章一樣對節點名或ip取Hash;如果拆分後的表存在一個伺服器中則可對拆分後的表名取Hash。
---------------------
作者:Jef冒牌紳士
來源:CSDN
原文:https://blog.csdn.net/longjef/article/details/53115519
版權聲明:本文為部落客原創文章,轉載請附上博文連結!