bbs 分庫分表

關於論壇數據庫的設計(分表分庫等-轉)

關於論壇數據庫的設計
文章分類:數據庫
一個簡單的論壇系統
1:包含下列信息:
2:每天論壇訪問量300萬左右,更新帖子10萬左右。
請給出數據庫表結構設計,並結合範式簡要說明設計思路。
一. 發帖主題和回覆信息存放在一張表,並在這個表中增加user_name字段 
對數據庫的操作而言,檢索數據的性能基本不會對數據造成很大的影響(精確查找的情況下),而對錶與表之間的連接卻會產生巨大的影響, 特別在有巨量數據的表之間;因此對問題的定位基本可以確定:在顯示和檢索數據時,儘量減少數據庫的連接以及表與表之間的連接; 
引用
1: user:用戶基本信息表 
字段有:user_id,user_name,email,homepage,tel,add...
2: forum_item:主題和回覆混合表 
字段有:id,parent_id,user_id,user_name,title,content,....
parent_id=0或者null表示是主題,否則=n表示是id=n那條帖子的回覆 
UserName字段是冗餘的,因此在用戶修改UserName的時候就會產生同步數據的問題,這個需要程序來進行彌補
二. 主題表和主題回覆分開保存 
引用
1: user:用戶基本信息表 
字段有:user_id,user_name,email,homepage,tel,add...
2: forum_topic:主題表 
字段有:id,user_id,title,content,....
3: forum_topic_back:主題回覆表 
字段有:id,topic_id,user_id,title,content,....
三. 主題表的內容單獨設計成一個表 
引用
1: user:用戶基本信息表 
字段有:user_id,user_name,email,homepage,tel,add...
2: forum_topic:主題表 
字段有:id,user_id,title,....
3: forum_topic_content:主題內容表 
字段有:id,topic_id,content
4: forum_topic_back:主題回覆表 
字段有:id,topic_id,user_id,title,content,....
四.用戶信息分2個表保存,並對相關表進行分表處理 
引用
1: 簡單用戶表 tb_user: 
id , username
2: 用戶詳細信息表 tb_userinfo 
id,userid , email , homepage , phone , address ...
3: 論壇主題表 tb_bbs 
id , userid , title , ip , repleycount , replyuserid , createtime , lastreplytime
4: 論壇內容標 tb_bbs_content (此表可按照bbsid進行分表存儲) 
id,bbsid , content;
5: 論壇回覆表 tb_bbs_reply (此表可按照bbsid進行分表存儲) 
id , bbsid , userid , content , replytime , ip
五.增加一個主題緩存表,取每個區的前面100條記錄 
引用
1: 簡單用戶表 tb_user: 
字段有:id , username
2: 用戶詳細信息表 tb_userinfo 
字段有:id,userid , email , homepage , phone , address ...
3: 論壇主題表 tb_bbs 
字段有:id , userid , title , ip , repleycount , replyuserid , createtime , lastreplytime
4: 論壇內容標 tb_bbs_content (此表可按照bbsid進行分表存儲) 
字段有:id,bbsid , content;
5: 論壇回覆表 tb_bbs_reply (此表可按照bbsid進行分表存儲) 
字段有:id , bbsid , userid , content , replytime , ip
6: 主題緩存表 tb_bbs_cache 
字段有:id , userid , title , ip , repleycount , replyuserid , createtime , lastreplytime
------------------------------------------------------------------------------ 
下面是針對上面的方案展開的討論:
1:方案一表面上看起來好像少查了一張表,但由於冗餘,因爲帖子數量極大,會佔用大量的空間。這種數據量大,但是對實時和數據絕對安全性要求較低的應用,大量使用緩存的話可以極大提高處理能力。
2:方案一你這麼設計的話,索引怎麼建比較好呢,還有就是會不會造成這個表過熱,還有…… 我覺得像論壇這樣的系統,使用緩存可以大大降低數據庫的負載
3:大家的意思是分成主題表、回覆表等多個表? 還是合成一個表然後做物理分區? 哪種更好呢?
4:再這麼高插入更新的頻率下 索引就有些不實用了,創建索引會降低插入更新的速度而且訪問量這麼大的情況下,索引不建議採用
5:就這樣的一個論壇,實時在更新、發帖、回帖。我覺得在數據庫上建立索引不太好,但是如果不建立索引如何來提高查詢等方面性能呢?
6:都是分佈式數據庫了。放在多個表中,直接關聯一點都沒問題。重要是橫向切分
7:認同分表,分庫,緩存的做法 
引用
問題分析: 
每天論壇訪問量300萬左右,更新帖子10萬左右。 
1. 讀寫比例在30:1左右, 應向讀取效率方面傾斜. 索引建立需參考常用讀取的主關鍵字. 
2. 每月數據在10W*30=300W. 可按月分表 
3. 每年帖子在300W*12=3600W, 推算數據不會小於30T. 可按年分庫
結構: 
用戶信息:獨立表,userid主鍵 
發帖、回帖:按月表存儲,帖子唯一ID主鍵,日期索引。 
帖子內容明細:按月存儲,帖子唯一ID主鍵
8:拿一張500萬的表來說事 
引用
更新的時候如果沒有索引的話 
更新時間大概需要30秒左右 指的是全表更新~~ 
而查詢某單行記錄 卻需要10秒左右~~
而加入索引的話 
更新時間差不多慢了一倍有餘 
而查詢記錄則縮減到毫秒級~~ 
快了百倍有餘~~
孰重孰輕 自己選
9:自己的一點經驗: 
引用
1.分表存儲; 
2.建立索引;SQL按所以查詢的速度還是很快的; 
3.避免整表掃描;先讀取主題,在按照主題ID讀取回復;再按照用戶ID讀取用戶;而不要使用關聯; 
4.使用緩存;
10:需要分3張表,且建立索引。。。 
理由如下: 
引用
1:建立3張表可以避免冗餘數據,維護起來方便。。。 
2:每天論壇訪問量300萬左右,可見主要的壓力來自於查詢,sql查詢的效率在於避免全表掃描,可見建立索引是必須的。。。 
3:關於創建索引會降低插入更新的速度這個問題是不存在的。。。 因爲,索引之所以會降低更新的速度的速度,是因爲在更新完對應字段後還需要更新對應字段的索引。 
4:看到更新帖子10萬左右,這句話是說,我們可能對發帖標題,發帖內容,回覆標題,回覆內容這4個字段做更新。。。需要注意的是,這四個字段並不是用來建立表連接的字段,爲了優化查詢速度我們不會在這四個字段上建立索引,所以從這道題目出發,我們建立的索引不會影響更新帖子的性能。。。
所以,我認爲最後的答案是建立3張表,在連接用到的字段上建立索引。。。
11:
引用
兩個表然後建一個視圖是否可行呢?
視圖也是很慢的。
12:每天就更新10萬個帖子,每天訪問那麼多,肯定是不能把所有的主貼放在一個表裏,大表分小表,建立常用字段的索引,然後配置緩存。級聯關係最好不要配置,等需要的時候再查詢。
13:雖然題目中沒有說明,但實際應用中,查閱帖子通常只會分頁顯示,而一頁最多也就顯示幾十個帖子,那麼實際上只要SQL語句構造得好,T_USER表其實只是跟一個只有幾十行結果集的的子查詢進行連接,應該基本不用擔心出現性能問題。
而且實際上,一個萬行級的表簡單關聯百萬行級的表(其實鎮魂歌數量級在我看來其實也算不上很大的表),在數據庫方面完全有很多優化方式,甚至可以通過提高硬件配置來改善性能,實在沒有很大必要進行結構上的冗餘。一旦結構有冗餘,爲了保證數據一致性,往往你還要消耗更多的資源,反而得不償失。
14:分表有垂直和水平分表 
引用
1:無論你拿多少記錄(甚至是1條),如果兩個大表關聯都可能會產生非常大的中間值,如果你排序(排序字段沒有用到索引),你都可能導致數據庫採用各種各樣的方式來計算。
2:索引會導致插入、更新記錄很慢,大家都是知道的。
3:水平分表可以解決這個問題,只要你能保證每個表只存適合的記錄數(例如100W一個表) (水平分區也可以解決IO的一些問題)
4:還有就讀寫分離,master是寫,slave是讀 (再加上cache,一般問題都還好了)
上面都是比較大的工作量,最好是保證你的數據庫設計是合理的(範式是第一步,然後考慮反範式),基本上也能滿足很多問題了。
15:方案四 把內容與其它信息分開的好處就是可以讓每個表的文件最小化,對數據庫操作壓力會減小,操作速度會快,還可以搭配緩存,把內容根據情況進行緩存,可以儘量很少訪問表數據。 
引用
1:對於上述分表方式也可以適用於分庫操作,這樣就降低了數據庫單庫的壓力,把壓力分散到各個機器 
2:我的做法就是儘量避免表關聯 
3:再就是對於sql語句儘量都保證索引有效,不能索引的sql,儘量採用能索引的高效方式解決
16:外圍的方案: 
引用
1 讀方面,生成靜態頁,或者緩存最新最熱的帖子。 
2 寫方面,估計主要是INSERT吧,這個可以異步操作的。所有的寫貼操作放到一個隊列然後批量執行插入數據庫操作。
17:方案四比較靠譜,再加上定期轉儲,海量的cache,大型論壇就此搞定。
18:我覺得應該還是使用3張表比較合適。 
引用
1:業務上說,很可能主貼跟回覆貼擁有不同的擴展,比如附件什麼的,都放在一張表裏面,假如主貼跟回覆存在個性需求,怎麼辦?無限加字段麼? 
2:主貼跟回覆在同一張表裏,會增大鎖表的機率。 
3:索引的確會降低表更新的速度,但是帶來的查詢效率提升也是很可觀的,因此我覺得,索引不能不用,但是要少用。 
4:建立表時,確實可以通過樓上某位仁兄回覆所言,用水平分表的方式,其實原理就是用先算再查嘛。 
5:在前端表現上,可以使用ajax等方式,分步驟取數據,比如主貼的內容先取出來,然後再逐步加載回覆信息等。
19:提高速度的關鍵: 
引用
1.建立索引並在查詢時充分利用; 
2.避免使用關聯,這樣避免整表掃描;使用關聯不如多次使用主鍵查詢來的快; 
3.一些處理的功能儘可能放到內存中來做,比如組織主題和回覆; 
4.使用靜態頁面也是個不錯的做法;
20:方案三是延續了hibernate二級緩存的思想, 對於經常更新的數據都設計成單獨表,這樣可以最大程度的利用hibernate緩存
21:沒有fast=true的設置,有人說or比in 好,exists比in 好,索引比全表掃描好,分區能提高查詢效率,但是分區要降低插入效率 
我要說的是,沒有fast=true的選項, 如果能找到一步,或者幾步公式化的方法能提高效率,那麼優化器自己就會做了,根本不用用戶擔心。 
假設 or比in好,數據庫優化器把in語法和or語法走的執行計劃一樣就可以了,何必折磨用戶呢。 
說點實際的,很多人張嘴就說,SQL優化就是避免全表掃描,不知道大家有沒有了解過索引查找的原理.索引查找數據,有兩步要做,第一步是索引中快速查詢,索引裏只存儲了對應表數據的rowid, 所以還有第二步,根據rowid去得到全部的數據, 所以需要一次磁盤i/o, 不要小看磁盤I/O,通過索引查詢出的結果比較多的時候,磁盤i/o的時間是非常大的,這個時候比全表掃描慢得多, 實際上,oracle 10g基於成本的優化器(CBO),選擇性不高的索引,優化器根本不會使用,而自動採用全表掃描的方式來做.
22:這個量級的bbs我設計過,當時是這樣做的(方案五): 
引用
共四個表: 
1. 用戶表 
2. 主題表(包含最後回覆信息,最後回覆人,最後回覆id等) 
3. 回覆表 
4. 主題緩存表(這個取每個區的前面100條記錄),一般來說負載最大的就是主題的第一頁,所以緩存表是個小表。
共3臺app集羣,1臺web,2臺oracle一主一備,運行下來速度還是可接受的。
23:不建議進行表的設計冗餘,感覺就想重複代碼一樣,有壞味道 
引用
1:緩存常用的頁面和數據 
2:讀寫表或庫分開(基於垂直分隔) 
3:數據庫可以進行垂直分隔(字段分到多個表中),再進行水平分隔(數據分到多個表中) 
4:論壇功能可以進行分隔,不同的服務器負責不同的功能,如圖片服務器,web服務器,郵件服務器等
總之,就是要細化分工
24:支持方案三的設計 
讀取的操作: 
引用
1:顯示帖子列表界面,如果主貼內容放在forum_topic表,那麼這就是冗餘的,假設都要獲取100個帖子,一行的數據長度越大,數據庫需要掃描的數據塊就越多,性能也越差。 
2:在打開一個帖子時,讀操作通過索引關聯到兩張表(forum_topic和forum_topic_content)性能消耗對整個數據庫來說不多。
寫帖子的操作: 
引用
發表帖子,對標題表和內容表分別作一個插入
更新非索引列不會引起索引更新: 
引用
只要被索引的列(例如回覆表的標題ID)不被頻繁更新,即使索引所在地行的其它列被頻繁update,索引也不會被更新從而產生性能消耗,一張表一天30萬次的索引更新,因它引起的性能消耗小到即使數據庫安裝在奔騰3單核CPU下都能輕鬆承擔下來, 爲什麼會有人對索引有這麼大的誤解呢?。對一個論壇(或者絕大部分的系統)來說,檢索(SELECT)數據耗費的系統資源遠遠高於更新數據(INSERT/UPDATE)本身,而索引是專門爲檢索數據服務的,難道就爲了節省更新數據的小小的性能消耗,付出檢索100條數據時需要數據庫掃描幾千萬上億條數據進行數據匹配的代價?如果是這樣的話,即使是有32核頂級CPU的數據庫作並行查詢都未必頂得住。
做數據庫設計,還是多瞭解數據庫的原理纔好。
25:數據庫切分是必須的。 
引用
1:垂直切分:用戶表、用戶信息表、主題表、主題內容表、回覆表 
2:水平切分:主題1、主題2、主題3、...、主題n 
3:緩存:緩存路由表 
4:再配合數據庫讀寫分離和集羣吧
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章