mysql schema设计_mongodb 的 schema 设计方法
mongodb 的schema設(shè)計(jì)方法
前言
mongodb是NoSQL的代表,從使用關(guān)系型數(shù)據(jù)庫(kù)(MySQL)到使用非關(guān)系型數(shù)據(jù)庫(kù)(mongodb),其中的一些以前的設(shè)計(jì)的思維慣性總是在不知不覺(jué)的影響著自己的決策。設(shè)計(jì)的思想有共同之處,也有很大的不同。mongodb的優(yōu)勢(shì)在于他表示數(shù)據(jù)的方式非常豐富。下面就來(lái)總結(jié)一些設(shè)計(jì)的原則和方法。
原則
schema的設(shè)計(jì)最重要的不是當(dāng)前設(shè)計(jì)的可擴(kuò)展性,對(duì)設(shè)計(jì)的可讀性,還是說(shuō)原來(lái)的設(shè)計(jì)三范式。最重要的在于,你的app一般展現(xiàn)出來(lái)的數(shù)據(jù)是什么結(jié)構(gòu),就設(shè)計(jì)成什么樣。取出即用。舉個(gè)例子來(lái)說(shuō),如果設(shè)計(jì)一個(gè)博客的schema,按照原來(lái)的方法, 你可能會(huì)設(shè)計(jì)成:
posts
{
_id: ,
title: ,
body: ,
author: ,
date:
}
comments
{
_id: ,
post_id: ,
author: ,
order:
}
tags
{
_id: ,
tag: ,
post_id:
}
但是更好的設(shè)計(jì)是:
{
_id: ,
author: ,
body: ,
comments : [
{
body: ,
email: ,
author: ,
},
...
{
...
}
],
date: ,
tags: [
...
],
title:
}
?
原來(lái)的設(shè)計(jì)范式的目標(biāo)
盡可能的減少數(shù)據(jù)庫(kù)數(shù)據(jù)修改的難度(減少數(shù)據(jù)冗余)
最小化數(shù)據(jù)庫(kù)設(shè)計(jì)擴(kuò)展的改動(dòng)
避免數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)時(shí)的歧義
在mongodb中:
默認(rèn)的來(lái)說(shuō)設(shè)計(jì)的時(shí)候是要避免數(shù)據(jù)冗余的
不存在這樣的問(wèn)題,因?yàn)閙ongo中的schema非常靈活,你可以隨時(shí)的改動(dòng)
由于設(shè)計(jì)的時(shí)候就盡可能的按照應(yīng)用需要的數(shù)據(jù)的形式設(shè)計(jì),取出即用,所以第三個(gè)問(wèn)題出現(xiàn)的概率也比較少
沒(méi)有約束怎么辦?
在mongo中,最經(jīng)常思考的問(wèn)題就是,沒(méi)有外鍵怎么保持?jǐn)?shù)據(jù)一致性?正如上述博客的第一種設(shè)計(jì)中,你在新插入一個(gè)評(píng)論的時(shí)候,數(shù)據(jù)庫(kù)是不會(huì)保證你這個(gè)post_id是不是真在在posts這個(gè)collection里面有對(duì)應(yīng)值。
解決的辦法就是像第二種設(shè)計(jì)中的做法,把他嵌入在posts這個(gè)collection.由于這個(gè)時(shí)候評(píng)論已經(jīng)是post的一部分,就再也不用擔(dān)心插入的評(píng)論沒(méi)有對(duì)應(yīng)到一篇博客的問(wèn)題。
沒(méi)有事務(wù)怎么辦?
在目前,mongodb是不支持事務(wù)的。也就是說(shuō),如果你一個(gè)業(yè)務(wù)需要修改好幾條記錄,你是沒(méi)辦法保證當(dāng)其中一個(gè)操作失敗的以后將其它操作回滾的,這種時(shí)候又應(yīng)該怎么辦?
雖然mongo沒(méi)有提供事務(wù),但是他提供了非常豐富的原子操作,我們應(yīng)該充分利用這一點(diǎn)。在關(guān)系型數(shù)據(jù)庫(kù)中,你可能有幾張表,然后要通過(guò)join的方式去鏈接。所以你需要事務(wù)去同時(shí)修改幾張表。但是在mongo中,在設(shè)計(jì)的時(shí)候你已經(jīng)prejoin了(就是你已經(jīng)把它們都嵌入在了同一個(gè)collection),你只需要直接一次修改整個(gè)post就可以實(shí)現(xiàn)事務(wù)的效果。
總的來(lái)說(shuō),解決的辦法有三個(gè):
重建你的設(shè)計(jì),使得你能通過(guò)原子操作一次把它們都修改完
在你的軟件中實(shí)現(xiàn)鎖的機(jī)制,用尋找和修改寫(xiě)一系列的測(cè)試來(lái)實(shí)現(xiàn)。
在大量的數(shù)據(jù)或者不嚴(yán)格的場(chǎng)景中,容忍這種錯(cuò)誤
典型的設(shè)計(jì)場(chǎng)景
一對(duì)一的關(guān)系
比如說(shuō)應(yīng)聘者和簡(jiǎn)歷的關(guān)系。除非嵌在一起會(huì)導(dǎo)致你的數(shù)據(jù)大于16MB(mongo的限制),你都應(yīng)該嵌在一起。做好的做法就是將一個(gè)比較少使用的嵌入一個(gè)經(jīng)常食用的當(dāng)中。
一對(duì)多的關(guān)系
比如說(shuō)城市和人的關(guān)系,博客和評(píng)論
對(duì)于像城市和人的關(guān)系這樣的,一個(gè)城市實(shí)在是對(duì)應(yīng)了太多太多的人。如果將人嵌入在城市中,不太合適。在城市信息嵌入在人中就更不合適了,因?yàn)檫€會(huì)產(chǎn)生大量數(shù)據(jù)冗余,更新信息也特別麻煩。這種情況下最好的做法就是分開(kāi)兩個(gè)collection,然后人的collection中每一條都有一個(gè)city字段,來(lái)對(duì)應(yīng)城市collection中的一條。
如果是像博客和評(píng)論這樣一個(gè)對(duì)應(yīng)的不是特別多的時(shí)候,最好的最法還是嵌進(jìn)去
多對(duì)多的關(guān)系
例如書(shū)和作者的關(guān)系,老師和學(xué)生的對(duì)應(yīng)關(guān)系
對(duì)于像書(shū)和作者這樣,比較少對(duì)應(yīng)比較少的,一個(gè)可行的做法就是分開(kāi)兩個(gè)collection。書(shū)collection中存一個(gè)authors數(shù)組,作者 collection中存一個(gè)books數(shù)組,互相對(duì)應(yīng)。這種做法不好的地方就在與要手動(dòng)維護(hù)數(shù)據(jù)一致性。另一個(gè)做法就是嵌在一起,這樣會(huì)有性能的提升,不過(guò)這種做法會(huì)導(dǎo)致數(shù)據(jù)冗余,看具體的情況來(lái)取舍。特別的像老師和學(xué)生這種關(guān)系,最好最好就是不要將老師嵌在學(xué)生中,因?yàn)楹芸赡芤粋€(gè)新來(lái)的老師就還沒(méi)有學(xué)生,這樣你就沒(méi)辦法把這位老師加入到系統(tǒng)中。
樹(shù)形結(jié)構(gòu)
一個(gè)典型的場(chǎng)景就是像amazon這樣的電商,一個(gè)商品分類(lèi)下可能有很多個(gè)子分類(lèi)。
其中的一個(gè)做法就是建立一個(gè)分類(lèi)的collection,然后每個(gè)分類(lèi)有一個(gè)parent_id字段,但是這樣不便于找到他所有的祖先。所以比較好的做法是再加一個(gè)ancesters的數(shù)組字段,記錄他所有的祖先的id,這樣就能方便的查詢(xún)到他的祖先和后代。
嵌入的優(yōu)勢(shì)
提高讀的效率。這意味著你要獲取數(shù)據(jù)只需要查詢(xún)一次數(shù)據(jù)庫(kù)就行了。
處理大文件
如果一個(gè)數(shù)據(jù)量特別大(大于16M),比如讀入一個(gè)100多M的mp4文件。這種情況下就需要用到GRIDFS.原理就是把他分割成一個(gè)一個(gè)小的塊
總結(jié)
以上是生活随笔為你收集整理的mysql schema设计_mongodb 的 schema 设计方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 福昕PDF高级企业版编辑器9.5 Fox
- 下一篇: mysql登录之后可以写什么_MYSQL