轉(http://www.cnblogs.com/liyulong1982/archive/2012/06/04/2535264.html)
基本的設計思想:
以業務的核心資料為中心,產生一張中間表,合并主要的業務資料。以簡化互連網程式設計的複雜度。這個設計可以用於電子商務、線上視頻等大部分互連網產品。下面以dangdang網為例說明:
舉例說明
如果我們需要做一個dangdang那樣的圖書銷售頁面,假設我們有200萬圖書,資料存放區到mysql,我們至少需要:
- 產生首頁推薦:包括推薦圖書的標題、價格、評分、評論資訊
- 產生熱門排行榜:包括圖書標題、價格、評分、評論資訊
- 產生圖書詳情頁:包括圖書標題、價格、評分、評論資訊
- 做一個搜尋引擎,可以根據標題,作者等等檢索圖書,檢索頁包含圖書標題、價格、評分、評論資訊
我們設計資料庫的時候,一般會這麼設計:
- 圖書基本資料表 (c_id, c_title, c_authors, c_publish … )
- 價格表 (c_id, c_price, c_discount …)
- 評分表 (c_id, c_score …)
- 評論表 (c_id, c_comment_count …)
- 首頁推薦圖書(c_pos, c_ids)
- xxx
- xxx
實現前3個需求並不太複雜,讀取每個表中的資料到記憶體,得到一個資料集,然後輸出靜態頁面即可。但是需要讀取很多個表,然後合并資料,這個操作仍然是很繁瑣的(相信你不會去用一條sql聯合很多個表吧),並且,隨著運營需求的變化,需要讀的表會越來越多,我們需要不斷的調整程式,以讀取更多的表。第4個搜尋的需求就比較麻煩一些了,本來我們有sphinx可以用,但是由於表的複雜關係,sphinx沒法用。
如果這些資訊都存在一張表中,上面的問題可以迎刃而解。比如這樣:(c_id, c_title, c_authors, c_publish, c_price, c_discount, c_score, c_comment_count ) 但是這種DB設計是不可接受的。原因有很多:
- 單條記錄過長,DB效率低
- 模組耦合度大,所有的模組都通過DB耦合在一起了
- 更重要的,如果我們某個模組的儲存結構不是mysql db怎麼辦呢。
我的設計方案:
表結構的設計和我們前面講的一樣,但是增加一張中間表,即那張包含了圖書所有資訊的大表(c_id, c_title, c_authors, c_publish, c_price, c_discount, c_score, c_comment_count … )。我們的程式每隔一段時間(比如2分鐘),把其他表中的資料merge起來同步到這個大表。我們前面需求中的商務邏輯都通過這張大表進行。現在只要一條sql就可以讀到所有圖書的資訊,然後我們用這個資訊產生頁面就可以了,不用再merge任何錶。
這個設計方案可能的缺點有哪些呢?
- 單條記錄過長,效率低。效率確實會低,但是沒有關係,我們這個表是唯讀,用來產生頁面的,用來檢索的,慢一點兒有什麼關係呢?如果你還嫌她慢,那就增加一層memcached/redis/leveldb的緩衝好了。
- 即時性問題,由於這個中間表是定時更新的,所以肯定有幾分鐘的延遲,但是有什麼關係呢,除了詳情頁中的價格和評論數,其他的資訊都不是敏感資訊,只要我們在詳情頁中即時擷取這些敏感資訊就可以了。
所以這些缺點都不是太大的問題。
這個設計方案有什麼優點呢?優點就多了
- 解決了搜尋的問題,讓我們盡情的用sphinx好了,即使資料存放區在了非mysql的儲存結構中,我們只要能把資料匯入到這個中間表,sphinx依然可用,而且只要一條簡單sql就搞定;
- 簡化了程式開發,所有擷取資料的過程都是1條sql搞定;
- 減少了程式耦合,如果沒這張中間表,如果我們想把其中一個模組遷移到其他DB或非DB的引擎,那麼很多程式都得修改,現在只要我們修改同步資料到中間表的程式就可以了。