使用 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`))

...
這種作法的主要問題在於日誌

針對每一個新的商品分類,都須要建立新的表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+款雲產品!

更多網易技術、產品、運營經驗分享請點擊。

文章來源: 網易雲社區

相關文章
相關標籤/搜索