分庫分表指的是將原有的單機單庫的單表橫向拆分到多機、多庫的多表前端
通常狀況下,分庫分表主要是爲了防止:java
過早優化是萬惡之源。分庫分表成本極高,不到萬不得已,最好不要分庫分表。mysql
分庫分表以前,咱們能夠先試試如下幾個選項。若是實在必要,再進行分庫分表。git
不少時候,分庫分表都是世上無事,庸人自擾。github
一千萬數據量的表,對咱們來講多是個大表,對MySQL來講,可能毫無壓力。MySQL自己對錶容量沒有作限制,有的用戶甚至用MySQL跑着50億行以上的大表。sql
通常狀況下,MySQL使用InnoDB存儲引擎,InnoDB默認的索引頁大小是16KB。InnoDB的索引使用的數據結構是B+Tree,一個索引節點存儲一個索引值加一個子節點地址。以INT類型的索引爲例,一個索引節點佔用4+4=8
個字節,一個索引頁能夠存放節點數16KB/8B=2K=2048
,構成了一棵2048叉樹。數據庫
若是在磁盤上查找索引,1000萬的數據量須要尋址log(10**7, 2048)=2.11
次,也就是2次IO。100億的數據量須要尋址log(10**10, 2048)=3.02
次,也就是3次IO。緩存
100億的數據量大約須要磁盤空間10**10*100B=1TB
,索引佔用大約10**10*8B=80GB
。服務器
因此,只要磁盤、內存和膽子都夠大,用MySQL存儲100億的數據徹底沒問題,也徹底能夠作到毫秒級的讀寫。數據結構
在對數據庫動手動腳前,先看看業務系統裏是否是有沒必要要的或者能夠整合的讀寫,是否是儲存了太多毫無價值的數據
適當添加緩存,能夠極大地減小數據庫的讀取操做
OLTP操做盡可能避免全表掃面
按業務分庫,按冷熱拆表
將一個表在物理層拆分爲多個表,對業務層徹底透明。不一樣的表分區能夠指定不一樣的物理磁盤,加大單表容量,提升併發讀寫速度,方便進行大表的備份與還原。
MySQL默認的存儲引擎是InnoDB,在不開啓壓縮的狀況下,空間浪費嚴重,通常1000萬行無索引的表佔用空間可達1GB。開啓壓縮後,大概能夠節省一半的空間。換用ARCHIVE
歸檔引擎,能夠大幅提升壓縮率,可是不支持索引,沒法進行OLTP查表。換用TokuDB
引擎進行折中,能夠在支持索引的狀況下,大幅壓縮磁盤空間佔用,大約能夠節省80%左右的存儲空間。
搭建MySQL集羣,分離讀寫,主機寫,從機讀,主機寫入同步從機。多主機可提升可用性,多從機可提升併發。
走完以上八步,通常狀況就不須要分庫分表了。
分庫分表主要有如下三種方式:
手工創建多庫多表,按照特定的分庫規則,讀取或寫入相應的表。通常用分表鍵對分表數量取餘肯定分表名。須要大量修改業務層代碼,與業務層耦合嚴重。性能相對較高,但不易維護與擴展。
將手工分庫分表的邏輯抽象爲一箇中間件,對Java來講是自定義javax.sql.DataSource
的實現,將分庫分表邏輯封裝在JDBC後面。對業務層相對透明,可是業界沒有太靠譜的免費解決方案。
代理MySQL鏈接,業務層不鏈接真實的MySQL服務器,鏈接的是MySQL服務器的代理。MySQL代理服務器根據配置好的分庫分表規則代理SQL請求,修改並轉發SQL到真實的MySQL服務器,最後對接收到的請求結果進行歸併處理。對業務層徹底透明,可是多開了一個服務,增長了維護成本。
No silver bullet, sometimes no necessay.
文章首發: https://baijifeilong.github.io/2018/11/27/mysql-sharding