云開(kāi)發(fā) 數(shù)據(jù)庫(kù)的設(shè)計(jì)

2020-07-22 15:31 更新

在我們要構(gòu)建一個(gè)項(xiàng)目(應(yīng)用程序)時(shí),通常第一件事情就要設(shè)計(jì)數(shù)據(jù)庫(kù)。和關(guān)系型數(shù)據(jù)庫(kù)將數(shù)據(jù)存儲(chǔ)在固定的表格(這些表格由行和列組成)里所不同的是,云開(kāi)發(fā)的數(shù)據(jù)庫(kù)使用結(jié)構(gòu)化的文檔來(lái)存儲(chǔ)數(shù)據(jù),不再是關(guān)系型數(shù)據(jù)庫(kù)里每個(gè)行列交匯處都必須有且只有一個(gè)值,它可以是一個(gè)數(shù)組、一個(gè)對(duì)象,或者更加復(fù)雜的嵌套。

一、數(shù)據(jù)庫(kù)的設(shè)計(jì)

1、設(shè)計(jì)數(shù)據(jù)庫(kù)需要預(yù)先思考哪些問(wèn)題

實(shí)現(xiàn)云開(kāi)發(fā)數(shù)據(jù)庫(kù)之前,需要了解存儲(chǔ)的數(shù)據(jù)的性質(zhì),如何存儲(chǔ)這些數(shù)據(jù),以及將如何訪問(wèn)它們,這需要你預(yù)先就要做出決定,進(jìn)而通過(guò)組織數(shù)據(jù)和頁(yè)面數(shù)據(jù)交互來(lái)獲得最佳性能。具體地說(shuō),你需要先預(yù)先思考如下問(wèn)題:

  • 頁(yè)面交互需要使用哪些基本對(duì)象,時(shí)間、地址、價(jià)格、富文本、圖片、商品屬性等等這些實(shí)際的信息在數(shù)據(jù)庫(kù)里對(duì)應(yīng)的是啥數(shù)據(jù)類(lèi)型?

  • 不同對(duì)象類(lèi)型之間的關(guān)系是一對(duì)一、一對(duì)多還是多對(duì)多?如商品分類(lèi)、詳情頁(yè)、評(píng)論頁(yè)、購(gòu)物車(chē)、會(huì)員信息、用戶信息、配送地址等等這些復(fù)雜的關(guān)系是怎么聯(lián)系起來(lái)的?

  • 云數(shù)據(jù)庫(kù)添加新對(duì)象的頻率有多高?集合里添加記錄的頻次是怎樣的?往內(nèi)嵌文檔里添加字段的值的頻率又是怎樣的?修改記錄以及記錄里的字段的值的頻率有多高?從數(shù)據(jù)庫(kù)中刪除記錄或記錄里的字段的頻率有多高?

  • 根據(jù)條件查詢數(shù)據(jù)庫(kù)的頻率有多高?是查詢記錄列表,還是記錄里某個(gè)字段的值?查詢記錄或記錄的值你將打算通過(guò)什么方式,是通過(guò)ID、字段、條件還是其他方式?

  • 創(chuàng)建的集合哪個(gè)是最重要的?哪個(gè)會(huì)放在首頁(yè)?哪個(gè)集合用戶訪問(wèn)并發(fā)量會(huì)比較大?并發(fā)量大的集合應(yīng)該怎么設(shè)計(jì)才能提升性能?

  • 哪些操作對(duì)數(shù)據(jù)的一致性要求比較高,需要進(jìn)行原子操作或事務(wù)操作?(后面的原子操作和事務(wù)會(huì)介紹)

  • 哪個(gè)集合或哪個(gè)集合的記錄的數(shù)據(jù)會(huì)增長(zhǎng)比較快,數(shù)據(jù)量會(huì)比較大?

  • 哪個(gè)集合或哪個(gè)集合的記錄會(huì)隨著業(yè)務(wù)的發(fā)展,字段會(huì)有很大的調(diào)整?

2、功能的背后也是數(shù)據(jù)庫(kù)的設(shè)計(jì)

應(yīng)用程序復(fù)雜業(yè)務(wù)功能的背后,都是簡(jiǎn)單的數(shù)據(jù),在設(shè)計(jì)數(shù)據(jù)庫(kù)的時(shí)候要清楚的知道哪些功能會(huì)執(zhí)行什么樣的數(shù)據(jù)操作,集合與集合、集合與字段之間有著什么關(guān)系。

  • 比如新聞應(yīng)用都會(huì)有文章列表以及文章詳情頁(yè),這是兩個(gè)功能,文章列表強(qiáng)調(diào)查詢的是符合條件的記錄;而文章詳情頁(yè)則是單個(gè)記錄下的字段;這兩者之間有什么差異?

  • 比如用戶除了有個(gè)人信息之外還有身份讀者與作者,讀者與作者的身份是怎么體現(xiàn)的?管理員、編輯等人的角色呢?不同的角色在處理數(shù)據(jù)上又有哪些不同?

  • 比如用戶的點(diǎn)贊、收藏、評(píng)論等這些是應(yīng)該放到用戶的集合里,還是應(yīng)該放到文章的集合里,或者是單獨(dú)拿出一個(gè)集合來(lái)存儲(chǔ)這些數(shù)據(jù)?選擇這個(gè)方式的依據(jù)是什么?

  • 前端通過(guò)表單增刪改查數(shù)據(jù)在數(shù)據(jù)庫(kù)里是怎么體現(xiàn)的?瀏覽頁(yè)面、上拉下滑、搜索、輪播、菜單等在數(shù)據(jù)庫(kù)是怎么體現(xiàn)的?

  • 文件上傳、圖片下載、地圖數(shù)據(jù)獲取、服務(wù)器時(shí)間等API是怎么與數(shù)據(jù)庫(kù)結(jié)合的?

二、反范式化與范式化設(shè)計(jì)

范式化(normalization) 是將數(shù)據(jù)像關(guān)系型數(shù)據(jù)庫(kù)一樣分散到不同的集合里,而不同的集合之間是可以通過(guò)唯一的ID來(lái)相互引用數(shù)據(jù)的。不過(guò)要引用這些數(shù)據(jù)往往需要進(jìn)行多次查詢或使用lookup進(jìn)行聯(lián)表查詢。

反范式化(denormalization) 則是將文檔所需的數(shù)據(jù)都嵌入到文檔的內(nèi)部,如果要更新數(shù)據(jù),可能整個(gè)文檔都要查出來(lái),修改之后再存儲(chǔ)到數(shù)據(jù)庫(kù)里,如果沒(méi)有更新指令這種可以進(jìn)行字段級(jí)別的更新,大文檔要新增字段性能會(huì)比較低下。反觀范式化設(shè)計(jì),由于集合比較分散,也就比較小,更新數(shù)據(jù)時(shí)可以只更新一個(gè)相對(duì)較小的文檔。

數(shù)據(jù)既可以內(nèi)嵌(反范式化),也可以采用引用(范式化),兩種策略并沒(méi)有優(yōu)劣之分,也都有各自的優(yōu)缺點(diǎn),關(guān)鍵是要選擇適合自己應(yīng)用場(chǎng)景的方案。完全反范式化的設(shè)計(jì)(將文檔所需要的所有數(shù)據(jù)都嵌入到一個(gè)文檔里面)可以大大減少文檔查詢的次數(shù)。如果數(shù)據(jù)更新更頻繁那么范式化的設(shè)計(jì)是一個(gè)比較好的選擇,而如果數(shù)據(jù)查詢更頻繁,而不需要怎么更新,那就沒(méi)有必要把數(shù)據(jù)分散到不同的集合而犧牲查詢的效率。對(duì)于復(fù)雜的應(yīng)用比如博客系統(tǒng)、商城系統(tǒng),只用一個(gè)集合(完全反范式化設(shè)計(jì))會(huì)導(dǎo)致集合過(guò)大,冗余數(shù)據(jù)更多,數(shù)據(jù)寫(xiě)入性能差等問(wèn)題,這時(shí)候就需要進(jìn)行一定的范式化設(shè)計(jì),也就是用更多的集合,而不是更大的集合

更適合內(nèi)嵌 更適合引用 說(shuō)明
內(nèi)嵌文檔最終會(huì)比較小 內(nèi)嵌文檔最終會(huì)比較大 一個(gè)記錄的上限是16M,業(yè)務(wù)會(huì)持續(xù)不斷增長(zhǎng)的數(shù)據(jù)不適合內(nèi)嵌,比如一個(gè)博客的文章會(huì)持續(xù)增長(zhǎng)就不能內(nèi)嵌到記錄里,博客的評(píng)論雖然也會(huì)增長(zhǎng),但是增長(zhǎng)量有限就可以內(nèi)嵌
記錄不會(huì)改變 記錄經(jīng)常會(huì)改變 當(dāng)新建一個(gè)記錄之后,如果業(yè)務(wù)只需要更新記錄里的字段或嵌套里的字段,而不是更新整個(gè)記錄,那可以用內(nèi)嵌
最終數(shù)據(jù)一致即可 中間階段的數(shù)據(jù)必須一致 內(nèi)嵌會(huì)影響數(shù)據(jù)的一致性,但是大多數(shù)業(yè)務(wù)并不需要強(qiáng)一致,比如把用戶評(píng)論內(nèi)嵌在文章集合里,用戶更改頭像后以前評(píng)論的頭像不會(huì)馬上更改,這不會(huì)有太大影響
文檔數(shù)據(jù)小幅增加 文檔數(shù)據(jù)大幅增加 如果業(yè)務(wù)需要大幅度更新記錄里的很多值或者大幅新增記錄,比如有大量用戶下訂單,用戶的訂單數(shù)據(jù)就不要內(nèi)嵌,而是以記錄的形式存在
數(shù)據(jù)通常需要二次查詢才能獲得 數(shù)據(jù)通常不包含在結(jié)果中 內(nèi)嵌文檔的可以通過(guò)一次查詢就能獲取到嵌套的數(shù)組和對(duì)象,比如文章記錄內(nèi)嵌套評(píng)論,查詢文章就能把該文章的評(píng)論全部獲取到,減少了查詢次數(shù)
需要快速查詢 需要快速增刪改 如果你的數(shù)據(jù)增刪改等寫(xiě)入比較頻繁,用嵌套數(shù)組和對(duì)象處理就會(huì)比較麻煩

像云開(kāi)發(fā)數(shù)據(jù)庫(kù)這種非關(guān)系型數(shù)據(jù)庫(kù),它的存儲(chǔ)單位是文檔,而文檔的字段是可以嵌套數(shù)組和對(duì)象的,這種內(nèi)嵌的方式把非關(guān)系型數(shù)據(jù)庫(kù)的表與表之間的關(guān)系嵌套在了一個(gè)文檔里,也就減少了需要跨集合操作的關(guān)聯(lián)關(guān)系。

三、內(nèi)嵌文檔(內(nèi)嵌數(shù)組或?qū)ο螅?/h3>

在前面我們了解到云開(kāi)發(fā)數(shù)據(jù)庫(kù)的一個(gè)文檔里可以內(nèi)嵌非常多的數(shù)據(jù),甚至做到一個(gè)完整的應(yīng)用只需一個(gè)集合。比如一個(gè)用戶,只有一個(gè)購(gòu)物車(chē)在關(guān)系型數(shù)據(jù)庫(kù)里,我們需要建兩張表來(lái)存儲(chǔ)數(shù)據(jù),一張表是存儲(chǔ)所有客戶信息的用戶列表User,還有一張存儲(chǔ)所有用戶訂單的訂單列表Order,但是云開(kāi)發(fā)數(shù)據(jù)庫(kù)可以將原本的多張表內(nèi)嵌成一張表。

{
  "name": "小明",
  "age": 27,
  "address":"深圳南山騰訊大廈",
  "orders": [{
    "item":"蘋(píng)果",
    "price":15,
    "number":3
  },{
    "item":"火龍果",
    "price":18,
    "number":4
  }]
  }
}

采用這個(gè)內(nèi)嵌式的設(shè)計(jì)模型,當(dāng)我們要查詢一個(gè)用戶的信息和他的所有訂單時(shí),就可以只通過(guò)一次查詢做到將用戶的信息、所有的訂單都獲取到,而不像關(guān)系型數(shù)據(jù)庫(kù)需要先在User表里查用戶的信息,再根據(jù)用戶的id去查所有訂單。

同樣一篇文章會(huì)有N個(gè)用戶去評(píng)論產(chǎn)生N條評(píng)論數(shù)據(jù),而這N條評(píng)論是只屬于這一篇文章的,不存在評(píng)論既屬于A文章,又屬于B文章的情況。這種我們還是可以采用反范式化設(shè)計(jì),將與該文章相關(guān)的評(píng)論都嵌入到這篇文章里:

{
  "title": "為什么要學(xué)習(xí)云開(kāi)發(fā)",
  "content": "云開(kāi)發(fā)是騰訊云為移動(dòng)開(kāi)發(fā)者提供的一站式后端云服務(wù)",
  "comments": [{
    "name": "李東bbsky",
    "created_on": "2020-03-21T10:01:22Z",
    "comment": "云開(kāi)發(fā)是微信生態(tài)下的最推薦的后臺(tái)技術(shù)解決方案"
  }, {
    "name": "小明",
    "created_on": "2020-03-21T11:01:22Z",
    "comment": "云開(kāi)發(fā)學(xué)起來(lái)太簡(jiǎn)單啦"
  }]
}

在我們要進(jìn)入文章的詳情頁(yè)時(shí),除了需要獲取文章的信息,還要一次性把評(píng)論都讀取出來(lái),這種反范式化內(nèi)嵌文檔就能做到,也就是可以通過(guò)一次查詢就能獲取到所有需要的數(shù)據(jù)。但是如果文章都是屬于大V一樣的熱點(diǎn),經(jīng)常會(huì)有幾千條幾萬(wàn)條的評(píng)論,將所有的評(píng)論都內(nèi)嵌到文章記錄里可能會(huì)存在記錄溢出(比如超過(guò)16M)、增刪改查效率也會(huì)下降,這個(gè)時(shí)候就不適合用內(nèi)嵌的方式,而是引用。

四、引用文檔

有時(shí)候數(shù)據(jù)與數(shù)據(jù)之間的關(guān)系會(huì)比較復(fù)雜,不再是一對(duì)一或者一對(duì)多的關(guān)系,比如共享協(xié)作時(shí),一個(gè)用戶可以發(fā)N個(gè)文檔,而一個(gè)文檔又有N個(gè)作者(用戶),這種N對(duì)N的復(fù)雜關(guān)系,使用內(nèi)嵌文檔就不那么好處理了。

試想一下如果你只創(chuàng)建一個(gè)用戶表,把A所參與編輯的文檔都內(nèi)嵌到相應(yīng)記錄的字段里,B用戶的也是,如果A,B用戶都參與編輯過(guò)同一份文檔,那么一份文檔就被內(nèi)嵌到了連個(gè)用戶的記錄了,如果這個(gè)文檔有N個(gè)作者,就會(huì)被重復(fù)內(nèi)嵌N次。如果我們只需要查用戶編輯過(guò)哪些文檔,這種方式就沒(méi)有問(wèn)題,但是如果要查一份文檔被多少個(gè)作者編輯過(guò),就比較困難了;如果文檔更新比較頻繁,那操作起來(lái)就更加復(fù)雜了,這時(shí)內(nèi)嵌文檔顯然不合適,應(yīng)該采用范式化的設(shè)計(jì)。

比如我們將用戶存儲(chǔ)到user集合里,將所有的文檔存儲(chǔ)到file集合里,集合與集合的會(huì)通過(guò)唯一的_id來(lái)連接,下面user集合主要存儲(chǔ)用戶的信息,而把需要引用的files集合記錄的_id也寫(xiě)到user集合里,

{
  "_id": "author10001",
  "name": "小云",
  "male":"female",
  "file": ["file200001","file200002","file200003"]
}
{
  "_id": "author10002",
  "male":"male",
  "name": "小開(kāi)",
  "books": ["file200001","file200004"]
}

而在files集合里,則存儲(chǔ)所有文檔的信息,在files集合里只需要有user集合引用的_id即可:

{
  "_id": "file200001",
  "title": "云開(kāi)發(fā)實(shí)戰(zhàn)指南.pdf",
  "categories": "PDF文檔",
  "size":"16M"
}
{
  "_id": "file200002",
  "title": "云數(shù)據(jù)庫(kù)性能優(yōu)化.doc",
  "categories": "Word文檔",
  "size":"2M"
}
{
  "_id": "file200003",
  "title": "云開(kāi)發(fā)入門(mén)指南.doc",
  "categories": "Word文檔",
  "size":"4M"
}
{
  "_id": "file200004",
  "title": "云函數(shù)實(shí)戰(zhàn).doc",
  "categories": "Word文檔",
  "size":"4M"
}

如果我們想一次性查詢用戶參與編輯了哪些文件以及相應(yīng)的文件信息,可以在云函數(shù)端使用聚合的lookup,這樣相當(dāng)于兩個(gè)集合整合到一個(gè)集合里面了。

const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
})
const db = cloud.database()
const _ = db.command  
const $ = db.command.aggregate
exports.main = async (event, context) => {
  const res = db.collection('user').aggregate()
    .lookup({
      from: 'files',
      localField: 'file',
      foreignField: '_id',
      as: 'bookList',
    })
  .end()
  return res
}

而如果我們要修改某個(gè)指定文檔的信息,直接根據(jù)files集合的_id來(lái)查詢就可以了。文檔更新一次,所有參與編輯該文檔的信息都會(huì)更新,保證了文件內(nèi)容的一致性。

值得一提的是,盡管我們將復(fù)雜的關(guān)系通過(guò)范式化設(shè)計(jì)把數(shù)據(jù)分散到了不同的集合,但是和關(guān)系型數(shù)據(jù)庫(kù)、Excel一個(gè)字段一列還是不一樣,我們還是可以把關(guān)系不那么復(fù)雜的數(shù)據(jù)用數(shù)組、對(duì)象的方式內(nèi)嵌。

如果每個(gè)用戶參與編輯的文檔特別多而每個(gè)文檔參與共同編輯的用戶又相對(duì)比較少,把file都內(nèi)嵌到user集合里就比較耗性能了,這時(shí)候可以反過(guò)來(lái),把user的id嵌入files集合里,所以數(shù)據(jù)庫(kù)的設(shè)計(jì)與實(shí)際業(yè)務(wù)有著很大的關(guān)系。

//由于file數(shù)組過(guò)大,user集合不再內(nèi)嵌file了
{
  "_id": "author10001",
  "name": "小云",
  "male":"female",
}


//把用戶的id嵌入到files集合里,相當(dāng)于以文檔為主,作者為輔
{
  "_id": "file200001",
  "title": "云開(kāi)發(fā)實(shí)戰(zhàn)指南.pdf",
  "categories": "PDF文檔",
  "size":"16M",
  "author":["author10001","author10002","author10003"]
}

這里再說(shuō)明一下,跨表查詢聯(lián)表查詢是兩碼事,跨表查詢我們可以通過(guò)集合與集合之間有關(guān)聯(lián)的字段(意義相同的字段)多次查詢來(lái)查找結(jié)果;而聯(lián)表查詢則是通過(guò)關(guān)聯(lián)的字段將多個(gè)集合的數(shù)據(jù)整列整列的合并到一起處理。如果你不需要返回跨集合的整列數(shù)據(jù),就不建議用聯(lián)表查詢,更不要妄圖聯(lián)N張表,能跨表查詢就跨表查詢。

五、數(shù)據(jù)庫(kù)設(shè)計(jì)的注意事項(xiàng)

1、數(shù)據(jù)庫(kù)的數(shù)據(jù)模式

云開(kāi)發(fā)數(shù)據(jù)庫(kù)的數(shù)據(jù)模式比較靈活,關(guān)系型數(shù)據(jù)庫(kù)要求你在插入數(shù)據(jù)之前必須先定義好一個(gè)表的模式結(jié)構(gòu),而云數(shù)據(jù)庫(kù)的集合 collection 則并不限制記錄 document 結(jié)構(gòu)。關(guān)系型數(shù)據(jù)庫(kù)對(duì)有什么字段、字段是什么類(lèi)型、長(zhǎng)度為多少等等,而云數(shù)據(jù)庫(kù)既不需要預(yù)先定義,而且記錄的結(jié)構(gòu)也沒(méi)有限制,同一個(gè)集合的記錄的字段可以有很大的差異。

這種靈活性讓對(duì)象和數(shù)據(jù)庫(kù)文檔之間的映射變得很容易。即使數(shù)據(jù)記錄之間有很大的變化,每個(gè)文檔也可以很好的映射到各條不同的記錄。當(dāng)然在實(shí)際使用中,同一個(gè)集合中的文檔最好都有一個(gè)類(lèi)似的結(jié)構(gòu)(相同的字段、相同的內(nèi)嵌文檔結(jié)構(gòu))方便進(jìn)行批量的增刪改查以及進(jìn)行聚合等操作。

隨著應(yīng)用程序使用時(shí)間的增長(zhǎng)和需求變化,數(shù)據(jù)庫(kù)的數(shù)據(jù)模式可能也需要相應(yīng)地增長(zhǎng)和改變。最簡(jiǎn)單的方式就是在原有的數(shù)據(jù)模式基礎(chǔ)之上進(jìn)行添加字段,這樣就能保證數(shù)據(jù)庫(kù)支持所有舊版的模式。比如用戶信息表,由于業(yè)務(wù)需要需要增加一些字段,比如性別、年齡,云數(shù)據(jù)庫(kù)可以很輕松添加,但是這會(huì)出現(xiàn)一些問(wèn)題,就是以往收集的用戶信息性別、年齡這些字段是空的,而只有新添加的用戶才有。如果業(yè)務(wù)的數(shù)據(jù)變動(dòng)比較大,文檔的數(shù)據(jù)模式也會(huì)存在版本混亂的沖突,這個(gè)在數(shù)據(jù)庫(kù)設(shè)計(jì)之初也是要思考的。

2、預(yù)填充數(shù)據(jù)

如果已經(jīng)知道未來(lái)要用到哪些字段,在第一次插入的時(shí)候就將這些字段預(yù)填充了,以后用到的時(shí)候就可以使用更新指令進(jìn)行字段級(jí)別的更新,而不再需要再給集合來(lái)新增字段,這樣的效率就會(huì)高很多。

{
  "_id":"user20200001",
  "nickname": "小明",
  "age": 27,
  "address":"",
  "school":[{
    "middle":""
  },{
    "college":""
  }]
}

比如簡(jiǎn)歷網(wǎng)站的用戶信息表的address、school,用戶登錄的時(shí)候不必填,但是投遞簡(jiǎn)歷前這些信息必填,如果沒(méi)有預(yù)先設(shè)置這些字段,收集這些信息時(shí)就需要使用doc對(duì)文檔進(jìn)行記錄級(jí)別的更新。

db.collection("user").doc("user20200001")
  .update({
    data:{
      "address":"深圳",
      "school":[{
        "middle":"華中一附中"
      },{
        "college":"清華大學(xué)"
      }]
    }
  })

但是如果預(yù)先設(shè)置了這些字段,就是使用更新操作符進(jìn)行字段級(jí)別的更新,當(dāng)集合越大,修改的內(nèi)容又比較少時(shí),使用更新操作符來(lái)更新文檔,性能會(huì)大大提升。

db.collection("user").doc("user20200001")
  .update({
    data:{
      "address":_.set("深圳"),
      "school.0.middle":_.set("華中一附中"),
      "school.1.college":_.set("清華")
    }
  })

3、考慮文檔的增長(zhǎng)

采用內(nèi)嵌文檔這種反范式化設(shè)計(jì)在查詢時(shí)是有很大的好處的,但是有一些文檔的更新操作,會(huì)在內(nèi)嵌文檔的數(shù)組里增加元素或者增加一個(gè)新字段,如果隨著業(yè)務(wù)的需求這類(lèi)操作導(dǎo)致文檔的大小變大,比如我們?yōu)榱朔奖惆言u(píng)論內(nèi)置到內(nèi)嵌文檔里,早期這樣的設(shè)計(jì)是沒(méi)有問(wèn)題的,但是如果評(píng)論常年累積的增加會(huì)導(dǎo)致內(nèi)嵌文檔過(guò)大,越是往后新增的評(píng)論會(huì)越是影響性能,而且云數(shù)據(jù)庫(kù)的一個(gè)記錄的上限是16M。如果出現(xiàn)這種數(shù)據(jù)增長(zhǎng)的情況,也會(huì)影響到反范式化的設(shè)計(jì)模式,那么你可能要重新設(shè)計(jì)下數(shù)據(jù)模型,在不同文檔之間使用引用的方式而非內(nèi)嵌的數(shù)據(jù)結(jié)構(gòu)。

由于更新指令不僅可以對(duì)數(shù)據(jù)進(jìn)行字段級(jí)別的微操(增刪改),而且還是原子操作,因此它不僅性能優(yōu)異還支持高并發(fā)。更值得一提的是,通過(guò)反范式化設(shè)計(jì)內(nèi)嵌文檔的方式,更新指令的原子操作可以替代一部分事務(wù)的功能,這個(gè)在原子操作和事務(wù)章節(jié)會(huì)有介紹。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)