此文已由做者溫正湖受權網易雲社區發佈。
mongodb
歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。數據庫
這是一篇MongoDB官網上的一篇文章,分析了使用MongoDB存儲商品分類信息相比其餘數據庫的優點,並講述瞭如何將其保存到MongoDB中。原址點擊:User case – Product Catalog。MongoDB中文社區有大神已將其翻譯成中文。在此不重複造車,直接轉載。歡迎一塊兒探討。性能優化
上述問題使用傳統的關係型數據庫也能夠解決,好比如下幾種方案架構
好比音樂專輯、電影這2種商品,有一部分共同的屬性,但也有不少自身特有的屬性,能夠建立2個不一樣的表,擁有不一樣的schema。運維
CREATE TABLE `product_audio_album` ( `sku` char(8) NOT NULL, ... `artist` varchar(255) DEFAULT NULL, `genre_0` varchar(255) DEFAULT NULL, `genre_1` varchar(255) DEFAULT NULL, ..., PRIMARY KEY(`sku`)) ... CREATE TABLE `product_film` ( `sku` char(8) NOT NULL, ... `title` varchar(255) DEFAULT NULL, `rating` char(8) DEFAULT NULL, ..., PRIMARY KEY(`sku`)) ...
這種作法的主要問題在於分佈式
針對每一個新的商品分類,都須要建立新的表性能
應用程序開發者必須顯式的將請求分發到對應的表上來查詢,一次查詢多種商品實現起來比較麻煩優化
CREATE TABLE `product` ( `sku` char(8) NOT NULL, ... `artist` varchar(255) DEFAULT NULL, `genre_0` varchar(255) DEFAULT NULL, `genre_1` varchar(255) DEFAULT NULL, ... `title` varchar(255) DEFAULT NULL, `rating` char(8) DEFAULT NULL, ..., PRIMARY KEY(`sku`))
將全部的商品存儲到一張表,這張表包含全部商品須要的屬性,不一樣的商品根據須要設置不一樣的屬性,這種方法使得商品查詢比較簡單,而且容許一個查詢跨多種商品,但缺點是浪費的空間比較多。.net
CREATE TABLE `product` ( `sku` char(8) NOT NULL, `title` varchar(255) DEFAULT NULL, `description` varchar(255) DEFAULT NULL, `price`, ... PRIMARY KEY(`sku`)) CREATE TABLE `product_audio_album` ( `sku` char(8) NOT NULL, ... `artist` varchar(255) DEFAULT NULL, `genre_0` varchar(255) DEFAULT NULL, `genre_1` varchar(255) DEFAULT NULL, ..., PRIMARY KEY(`sku`), FOREIGN KEY(`sku`) REFERENCES `product`(`sku`)) ... CREATE TABLE `product_film` ( `sku` char(8) NOT NULL, ... `title` varchar(255) DEFAULT NULL, `rating` char(8) DEFAULT NULL, ..., PRIMARY KEY(`sku`), FOREIGN KEY(`sku`) REFERENCES `product`(`sku`)) ...
上述方案將全部商品公共的屬性提取出來,將公共屬性存儲到一張表裏,每種商品根據自身的須要建立新的表,新表裏只存儲該商品特有的信息。翻譯
全部的數據按照 的3元組的形式存儲,這個方案其實是把關係型數據庫當KV存儲使用,模型簡單,但應對複雜的查詢不是很方便。
ENTITY | ATTRIBUTE | VALUES |
---|---|---|
sku_00e8da9b | type | Audio Album |
sku_00e8da9b | title | A Love Supreme |
sku_00e8da9b | … | … |
sku_00e8da9b | artist | John Coltrane |
sku_00e8da9b | genre | Jazz |
sku_00e8da9b | genre | General |
… | … | … |
MognoDB 與關係型數據庫不一樣,其無schema,文檔內容能夠很是靈活的定製,能很好的使用上述商品分類存儲的需求; 將商品信息存儲在一個集合裏,集合裏不一樣的商品能夠自定義文檔內容。
好比一個音樂專輯能夠相似以下的文檔結構
{ sku: "00e8da9b", type: "Audio Album", title: "A Love Supreme", description: "by John Coltrane", asin: "B0000A118M", shipping: { weight: 6, dimensions: { width: 10, height: 10, depth: 1 }, }, pricing: { list: 1200, retail: 1100, savings: 100, pct_savings: 8 }, details: { title: "A Love Supreme [Original Recording Reissued]", artist: "John Coltrane", genre: [ "Jazz", "General" ], ... tracks: [ "A Love Supreme Part I: Acknowledgement", "A Love Supreme Part II - Resolution", "A Love Supreme, Part III: Pursuance", "A Love Supreme, Part IV-Psalm" ], }, }
而一部電影則能夠存儲爲
{ sku: "00e8da9d", type: "Film", ..., asin: "B000P0J0AQ", shipping: { ... }, pricing: { ... }, details: { title: "The Matrix", director: [ "Andy Wachowski", "Larry Wachowski" ], writer: [ "Andy Wachowski", "Larry Wachowski" ], ..., aspect_ratio: "1.66:1" }, }
全部商品都擁有一些共同的基本信息,特定的商品能夠根據須要擴展獨有的內容,很是方便; 基於上述模型,MongoDB 也能很好的服務各種查詢。
db.products.find({'type': 'Film', 'details.actor': 'Keanu Reeves'}).sort({'details.issue_date', -1})
上述查詢也能夠經過創建索引來加速
db.products.createIndex({ type: 1, 'details.actor': 1, 'details.issue_date': -1 })
db.products.find({ 'type': 'Film', 'title': {'$regex': '.*hacker.*', '$options':'i'}}).sort({'details.issue_date', -1})
可創建以下索引來加速查詢
db.products.createIndex({ type: 1, details.issue_date: -1, title: 1 })
當單個節點沒法知足海量商品信息存儲的需求時,就須要使用MongoDB sharding來擴展,假定大量的查詢都是都會基於商品類型,那麼就可使用商品類型字段來進行分片。
db.shardCollection('products', { key: {type: 1} })
分片時,儘可能使用複合的索引字段,這樣能知足更多的查詢需求,好比基於商品類型以後,還會常常根據商品的風格標籤來查詢,則能夠把商品的標籤字段做爲第二分片key。
db.shardCollection('products', { key: {type: 1, 'details.genre': 1} })
若是某種類型的商品,擁有相同標籤的特別多,則會出現jumbo chunk的問題,致使沒法遷移,能夠進一步的優化分片key,以免這種狀況。
db.shardCollection('products', { key: {type: 1, 'details.genre': 1, sku: 1} })
加入第3分片key以後,即便類型、風格標籤都相同,但其sku信息確定不一樣,就確定不會出現超大的chunk。
網易雲MongoDB 服務爲開發者提供了一站式的 MongoDB 雲端解決方案,包括提供三節點複製集的高可用架構,故障切換,並提供專業的備份、監控以及性能優化方案,完全免除開發者的運維煩惱。點擊可免費試用。
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易技術、產品、運營經驗分享請點擊。
相關文章:
【推薦】 代碼混淆防止APP被反編譯指南
【推薦】 簡單歸納一下《金字塔原理》的主要內容?
【推薦】 分佈式存儲系統可靠性系列二:系統估算示例