此文已由做者溫正湖受權網易雲社區發佈。數據庫
歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。性能優化
這是一篇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`))
...
這種作法的主要問題在於日誌
針對每一個新的商品分類,都須要建立新的表code
應用程序開發者必須顯式的將請求分發到對應的表上來查詢,一次查詢多種商品實現起來比較麻煩排序
全部商品存儲到單張表
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`))
將全部的商品存儲到一張表,這張表包含全部商品須要的屬性,不一樣的商品根據須要設置不一樣的屬性,這種方法使得商品查詢比較簡單,而且容許一個查詢跨多種商品,但缺點是浪費的空間比較多。
提取公共屬性,多表繼承
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`))
...
上述方案將全部商品公共的屬性提取出來,將公共屬性存儲到一張表裏,每種商品根據自身的須要建立新的表,新表裏只存儲該商品特有的信息。
Entity Attribute Values 形式存儲
全部的數據按照 的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
… … …
MongoDB 解決方案
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+款雲產品!
更多網易技術、產品、運營經驗分享請點擊。
文章來源: 網易雲社區