在大容量,高負荷的web系統中,對數據庫進行一系列拆分,可有效提高數據庫容量和性能。在初學程序的早期,程序員一般都喜歡按傳統數據庫設計模式,設計爲單庫和單一功能表的結構,這樣的結構在數據量和併發量達到必定程度以後,會出現嚴重性能問題和維護問題。在出現問題的時候才着手進行優化,會很是痛苦,因此應該在系統架設之初就考慮好以後會出現的問題。
目前有些數據庫策略是採用單庫結構,而後經過同步分發到數臺服務器實現讀寫分離。我的以爲這樣的策略很是笨拙,仍是想辦法將其分隔開來好,不然每臺機器的內存都很容易超支。
通常只對數據量比較大的表進行拆分,這應該沒有什麼異議;還有一種是有可能會進行維護的比較重要的表,好比文章目錄表,若是有從其它系統倒數據進來的可能的話,也要拆掉,否則倒數據時一不當心把目錄表弄壞了,發現忘了備份,那真是欲哭無淚。
下面來分析一下:
1、時間結構
若是業務系統對時效性較高,好比新聞發佈系統的文章表,能夠把數據庫設計成時間結構,按時間分有幾種結構:
1) 平板式
表相似:
article_200901
article_200902
article_200903
用年來分仍是用月可自定,但用日期的話表就太多了,也沒這必要。通常建議是按月分就能夠。
這種分法,其難處在於,假設我要列20條數據,結果這三張表裏都有2條,那麼業務上頗有可能要求讀三次表。若是時間長了,有幾十張表,而每張表是0條,那不就是要讀完整個系統的表才行麼?另外這個結構,要做分頁是比較難實現的。
主鍵:在這個系統中,主鍵是13位帶毫秒的時間戳,不要用自動編號,不然難以經過主鍵定位到表,也能夠在查詢時帶上時間,但比較煩瑣。
2) 歸檔式
表相似:
article_old
article_new
爲了解決平板式的缺點,能夠採用時間歸檔式設計,能夠看到這個系統只有兩張表。一張是舊文章表,一張是新文章表,新文章表放2個月的信息,天天按期把2個月中的最先一天的文章納入舊錶中。這樣一方面能夠解決性能問題,由於通常新聞發佈系統讀取的都是新的內容,舊的內容讀取少;第二能夠委婉地解決功能問題,好比平板式所說的問題,在歸檔式中最多也只須要讀2張表就完成了。
歸檔式的缺點在於舊錶容量仍是相對比較大,若是業務容許,可對舊錶中的超舊內容進行再歸檔或直接清理掉。
2、版塊結構
若是按照文章的所屬版塊進行拆表,好比新聞、體育版塊拆表,一方面可使每一個表數據量分離,另外一方面是各版塊之間相互影響可降到最低。假如新聞版塊的數據表損壞或須要維護,並不會影響到體育版塊的正常工做,從而下降了風險。版塊結構同時經常使用於bbs這樣的系統。
板塊結構也有幾種分法:
1) 對應式
對於版塊數量很少,並且較爲固定的形式,就直接對應就好。好比新聞版塊,能夠分出新聞的目錄表,新聞的文章表等。
news_category
news_article
sports_category
sports_article
可看到每個版塊都對應着一組相同的表結構,好處就是一目瞭然。在功能上,由於版塊之間仍是有一些隔閡,因此須要聯合查詢的需求很少,開發上比時間結構的方式要輕鬆。
主鍵:依舊要考慮的,在這個系統中,主鍵是版塊+時間戳,單純的時間戳或自動編號也能用,查詢時要記得帶上版塊用於定位表。
2) 冷熱式
對應式的缺點是,若是版塊數量很大並且不肯定,那要分出的表數量就太多了。舉個例子:百度貼吧,若是按一個詞條一個表設計,那得有多少張表呢?
用這樣的方式吧。
tieba_汽車
tieba_飛機
tieba_火箭
tieba__unite
這個表汽車、火箭表是屬於熱門表,定義爲新建的版塊放在unite表裏面,待到其超過一萬張主貼的時候纔開對應表結構。由於在貼吧這種系統中,冷門版塊確定比熱門版塊多得多,這些冷門版塊一般只有幾張帖子,爲它們開表也太浪費了;同時熱門版塊數量和訪問量等,又比冷門版塊多得多,很是有特色。
unite表還能夠擴展成哈希表,利用詞條的md5編碼,能夠分紅n張表,我算了一下,md5前一位可分16張表,兩位便是256張表。
tieba_unite_ab
tieba_unite_ac
...
3、哈希結構
哈希結構一般用於博客之類的基於用戶的場合,在博客這樣的系統裏有幾個特色,1是用戶數量很是多,2是每一個用戶發的文章數量都較少,3是用戶發文章不按期,4是每一個用戶發得很少,但總量仍很是之大。基於這些特色,用以上所說的任何一種分表方式都不合適,一沒有固定的時效不宜用時間拆,二用戶不少,並且還恰恰都是冷門,因此也不宜用版塊(用戶)拆。
哈希結構在上面有所說起,既然按每一個用戶很差直接拆,那就把一羣用戶歸進一個表好了。
blog_aa
blog_ab
blog_ac
...
如上所說,md5取前兩位哈希能夠達到1296張表,若是以爲不夠,那就再加一位,總數可達46656張表,還不夠?
表的數量太多,要建立這些表也是挺麻煩的,能夠考慮在程序裏往數據庫insert以前,多執行一句判斷表存在與否並建立表的語句,很實用,消耗也並不很大。
主鍵:依舊要考慮的,在這個系統中,主鍵是用戶ID+時間戳,單純的時間戳或自動編號也能用,但查詢時要記得帶上用戶名用於定位表。
4、總分結構
以上的這些結構,根據每一個業務系統,能想出的估計還有不少。不過如今互聯網業務愈來愈複雜了,有些時候,單一的拆分法還不能實現需求,須要幾種拆分方案一塊兒實施,多管齊下,這時候其中的邏輯會讓人繞暈。我就開發過一個系統,僅僅是將哈希結構和時間結構混着一用,以爲邏輯就至關複雜。
因此,除了拆表以外,按最原始的單庫單表,再建一個總表,是很是有利的架構。在這個架構中,每次往數據庫會寫入兩倍數據,讀取主要依賴拆表提高性能,總表用於實現拆表後難以實現的功能而且用於天天的定時備份;另外總表和分表還相互是一個完整的備份,任何一個分表損壞或數據不正常,均可以從總表中讀到正確的數據並恢復,反之亦然。
在總分結構中,讓人感到質疑的是總表的性能和可維護性。個人方案是總表可採用相對能保證穩定的一些服務軟件和架構,例如oracle,或 lvs+pgpool+PostgreSQL,重點保證數據穩定;相對的,分表就用輕量級的mysql,重點在於速度。可以對總分表各採用不一樣的軟件和方案,也是總分結構的一大特色。
總結:如何經過拆表來優化系統,最基本的是要按業務需求和特色分析。本文僅僅是提供了幾種基本方法,具體工做要先動腦好好想,千萬不可亂套,用錯了工做量要加十倍噢。mysql