提高mysql讀寫性能之分庫分表

mysql 分庫分表

上一篇文章我們介紹了mysql的主從讀寫分離,這裏我們介紹分庫分表的應用。

什麼是分庫分表呢,分就是拆分,也就是將一個數據表(庫)拆分成多個。那有什麼作用呢,可以分散流量,和主從類似,主從是將讀寫流量分開,方便擴展,這裏是將表(庫)分開方便擴展。同時流量分散,比如一張上億數據的表,那麼查詢起來肯定很慢,但是要是水平拆分成多張表,每張表的數據量就會很小,查詢速度就會變快。

分庫分表一般分爲兩種,一種是水平拆分,一種是垂直拆分。

垂直拆分

垂直拆分,比如你現在所有的表都放在一個庫中,那麼這個庫會很龐大,那我們可以按照業務來拆分成多個數據庫,比如用戶相關的用戶庫,交易相關的交易庫等等。

這種拆分理念和微服務的理念差不多,微服務同樣是按照業務來劃分。

這樣處理用戶相關的只會訪問用戶庫,不會對其他數據庫造成壓力,同樣的,我們用戶庫有壓力也方便單獨擴展。

表的垂直拆分同樣的道理,不過一般在表設計的時候就已經拆分好了,不應該出現一張表還能進行拆分的情況。

水平拆分

水平拆分,比如你現在表數據量過大,一張表擁有上億的數據量,這時候就要把一張表拆分成多張表。

怎麼拆分呢,一般有兩種方法,比如

取餘法

假設我們現在將一張千萬級的表拆分成100個表,每張表的數據大概在十萬量級。那我們怎麼確定一條數據應該存在哪張表中呢,我們可以對數據的id進行取餘操作,也就是 id % 100 = 1那就存放在一號表中, 2就放在2號表,以此類推。也可以hash一下再取餘,比如hash(id) % 100。

分段法

也就是我們確定區間,比如前十萬用戶存在一號表,然後十萬十萬的類推,或者根據時間,每個月的用戶一張表都可以。

join問題

那現在有一個問題,比如查詢用戶的時候需要查詢出用戶的餘額,以前我們是join的方式聯查,那現在分成多個表之後就沒法join了,我們只能先查詢出用戶信息,然後再查詢出這個用戶的餘額

條件查詢問題

經過分表之後,數據分佈在不同的地方,我們如果是查詢id是5的用戶,很簡單,5 % 100就可以知道在哪張表中了,但是我們要查詢姓名是張三的用戶怎麼辦呢。我們要去查詢哪張表呢,這個時候我們就需要做一個映射了,比如有一張表存儲id 和 姓名的映射,我們通過這張映射表查詢到張三的id,在id % 100來確定查詢哪張表。這張映射表同樣要分表,那我們怎麼確定張三在哪張映射表中呢,我們可以用hash(張三) % 100的方式確定在哪張映射表中。

主鍵唯一問題

還有一個問題,原來我們在一張表中,主鍵只要做到表唯一,我們現在100張表,怎麼保證這條記錄的主鍵id在這100張表中都是唯一的呢。

有一種方法,我們生成唯一的uuid就可以了,但是這樣有幾個問題

  • 有序性

一般來說,我們都會使用自增id,保持id有序並且單調遞增,爲什麼呢,因爲mysql的innoDb引擎使用B+樹存儲索引數據,而主鍵就是一種索引。

索引數據在B+樹種有序存儲,這樣不管是寫入還是查詢的效率都會很高,而如果是無序的,那麼寫入和查詢的效率就會降低。

因爲有序的時候可以使用很多搜索算法提高查詢效率。

  • 表達性

uuid不具備任何表達性,沒辦法看到從種看到這個uuid是屬於哪個業務的。

知道了問題所在,我們就可以解決了。

在一下篇文章中會介紹snowFlake算法來解決這個問題。

感謝極客時間的唐揚老師開設的《高併發系統設計》專欄,這裏的內容都是學完以後自己的總結,提煉,思考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章