公司技術分享mongodb講解

mongdob的介紹

官話:

MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.

MongoDB是爲現代應用程序開發人員和雲時代構建的基於文檔的通用分佈式數據庫。

這裏我們看到這麼幾個關鍵字:文檔分佈式數據庫
天生就是分佈式數據庫,沒錢別用?

MongoDB is a document database, which means it stores data in JSON-like documents. We believe this is the most natural way to think about data, and is much more expressive and powerful than the traditional row/column model.

MongoDB是一個文檔數據庫,這意味着它將數據存儲在類似JSON的文檔中。我們認爲這是最自然的數據處理方式,比傳統的行/列模型更具表現力和功能。

關鍵字:類似JSON? 那到底是不是JSON

類JSON格式的優點

官話:

  • The most natural and productive way to work with data.
  • Supports arrays and nested objects as values.
  • Allows for flexible and dynamic schemas.
  • 處理數據的最自然,最有效的方式。
  • 支持數組和嵌套對象作爲值。
  • 允許靈活和動態的schemas。
{
  "_id": "5cf0029caff5056591b0ce7d",
  "firstname": "Jane",
  "lastname": "Wu",
  "address": {
    "street": "1 Circle Rd",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90404"
  },
  "hobbies": ["surfing", "coding"]
}
> db.users.find({ "address.zip" : "90404" })
{ "_id": "5cf0029caff5056591b0ce7d", "firstname": "Jane", "lastname": "Wu", "address":{}}
{ "_id": "507f1f77bcf86cd799439011", "firstname": "Jon", "lastname": "Davis", "address":{}}
{ "_id": "5349b4ddd2781d08c09890f3", "firstname": "Jim", "lastname": "White", "address":{}}
{ "_id": "5bf142459b72e12b2b1b2cd", "firstname": "Jeff", "lastname": "Taylor", "address":{}}
{ "_id": "5cf003283b23d04a40d5f88a", "firstname": "Jerry", "lastname": "Miller", "address":{}}
{ "_id": "5bf142459b72e12b2b1b2cd", "firstname": "Jai", "lastname": "Williams", "address":{}}
{ "_id": "5cf0036deaa1742dd225ea35", "firstname": "Jess", "lastname": "Johnson", "address":{}}
{ "_id": "54495ad94c934721ede76d90", "firstname": "Jill", "lastname": "Brown", "address":{}}
{ "_id": "566eb3c704c7b31facbb0007", "firstname": "Janet", "lastname": "Jones", "address":{}}
{ "_id": "5a999cc461d36489a27f2563", "firstname": "Jan", "lastname": "Smith", "address":{}}

強大的查詢

Rich and expressive query language that allows you to filter and sort by any field, no matter how nested it may be within a document.

無論您在文檔中有多嵌套,都可以按任何字段進行過濾和排序。

Support for aggregations and other modern use-cases such as geo-based search, graph search, and text search.

支持聚合和其他現代用例,例如基於地理的搜索,圖形搜索和文本搜索。
查詢本身就是JSON,因此很容易組合。

Queries are themselves JSON, and thus easily composable. No more concatenating strings to dynamically generate SQL queries.

不再需要串聯字符串來動態生成SQL查詢。

什麼是文檔(Document)

百度百科:

1:在操作系統中,文檔是文件夾。你們可以看桌面上的我的文檔屬性’類型‘

2:在軟件中,新建的文檔,是文件。(一般爲:計算機用語,文件的另一種稱呼,一般將WORD,EXCEL等文字編輯軟件產生的文件叫做文檔)

mysql說:插入一條記錄 它真的插入了一條記錄;(行/列形式的)

mongodb說:不,我插入了一個文檔;(類json格式的)

個人認爲:mongodb中的文檔只是爲了區別SQL行/列那種形式的一種叫法;

官話:

BSON is a binary format in which zero or more ordered key/value pairs are stored as a single entity. We call this entity a document.

鏈接:http://bsonspec.org/spec.html

BSON是一種二進制格式,其中零個或多個有序 鍵/值對 存儲爲單個實體。
我們將此實體稱爲文檔。

類JSON格式 – BSON

Bin­ary JSON的縮小。

以下格式不是json嗎?

{
  "_id": "5cf0029caff5056591b0ce7d",
  "firstname": "Jane",
  "lastname": "Wu",
  "address": {
    "street": "1 Circle Rd",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90404"
  },
  "hobbies": ["surfing", "coding"],
  "joined": new Date("2016-05-01") //???是json嗎?
}

json支持的數據類型

① 數組(array)、對象(object)
② 字符串(string)、數字(number)、布爾型(boolean)、NULL值

BSON支持的數據類型

JSON的基礎上還支持
① Date
② BinData 二進制數據

並且其遍歷速度更快:
BSON在文檔中添加了一些“額外”信息,例如字符串和子對象的長度。
這樣可以使遍歷更快

mongodb的安裝

安裝過程不建議參考官網,安裝細節建議參考官網;

https://docs.mongodb.com/manual/tutorial/install-mongodb-enterprise-on-os-x/

配置文件:
https://docs.mongodb.com/manual/reference/configuration-options/#configuration-file

mongodb權限

https://docs.mongodb.com/manual/tutorial/enable-authentication/index.html

1、MongoDB是沒有默認管理員賬號,所以要先添加管理員賬號,再開啓權限認證。
2、切換到admin數據庫,添加的賬號纔是管理員賬號。
3、用戶只能在用戶的認證數據庫登錄,包括管理員賬號。
4、管理員可以管理所有數據庫,但是不能直接管理其他數據庫,要先在admin數據庫認證(登錄)後纔可以

mongodb身份:
① 普通用戶
② admin 管理員 可以查看所有數據庫,但是隻能操作認證數據庫
③ root管理員

啓用配置

security:
    authorization: enabled

完整的:

systemLog:
    destination: file
    path: D:\mongodbdata\log\mongod.log
    logAppend: true
storage:
    journal:
        enabled: true
    dbPath: D:\mongodbdata\db
net:
    bindIp: 127.0.0.1
    port: 27017
security:
    authorization: enabled

創建admin用戶

執行命令:

use admin
db.createUser(
  {
    user: "myUserAdmin",
    pwd: "abc123",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

結果:

Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}

在這裏插入圖片描述

內置的角色:Built-In Roles

創建普通用戶

>use test
> db.createUser(
{
    user:"test1",
    pwd: "test1",
    roles: [{ role: "readWrite", db: "test"}]
  }
 )

結果:

Successfully added user: {
        "user" : "test1",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "test"
                }
        ]
}

切換到其他數據庫

下面的命令可以到robo 3T 中執行,但是必須得一起執行

use myTest
db.mytest.find()

這圖是在window中執行。
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

mongodb 基本概念

在這裏插入圖片描述

SQL術語 mongodb 術語 說明
database database 數據庫
table collection 數據庫表、集合
row document 數據記錄行、文檔
column field 數據字段
index index 索引
table joins $lookup 錶鏈接、 只能關聯未分片的表
primary key primary key 主鍵,MongoDB自動將_id字段設置爲主鍵

關於$lookup:
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/index.html#lookup-aggregation

mongodb的客戶端

在本機安裝好server端後,需要客戶端進行連接,爲了熟悉命令和操作,建議使用:Robomongo

參考地址:https://robomongo.org/

在這裏插入圖片描述

mongodb的CURD

更新

db.girl.update({firstname:"Jane"}, {$set:{lastname:"Yu"}}, false, false)

第三個參數:true,表示query不匹配,就新增,否則就更新
第四個參數:true,表示匹配多條,就都更新,否則就更新第一條

https://docs.mongodb.com/manual/reference/method/db.collection.update/

分佈式事務

1、在4.0版中,MongoDB支持副本集上的多文檔事務。
2、在版本4.2中,MongoDB引入了分佈式事務,它增加了對分片羣集上多文檔事務的支持,併合並了對副本集上多文檔事務的現有支持。

https://docs.mongodb.com/manual/core/transactions/

當一個事務寫入多個分片時,並非所有外部讀取操作都需要等待已提交事務的結果在所有分片上可見。
例如,如果提交了一個事務,並且在分片A上可以看到寫1,
但是在分片B上還看不到寫2,則外部讀的安全級別設置爲“local,那麼可以讀取寫1的結果而看不到寫2。

在大多數情況下,與單文檔寫入相比,多文檔事務產生的性能成本更高,並且多文檔事務的可用性不應代替有效的schema設計。
在許多情況下,非規範化數據模型(嵌入式文檔和數組)對於我們的數據和用例依舊是最佳的。
也就是說,在許多情況下,對數據進行適當的建模將最大程度地減少對多文檔事務的需求。

Java 分佈式事務示例代碼:

/*
  For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
  String uri = "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/admin?replicaSet=myRepl";
  For a sharded cluster, connect to the mongos instances; e.g.
  String uri = "mongodb://mongos0.example.com:27017,mongos1.example.com:27017:27017/admin";
 */
// 拿到客戶端對象
final MongoClient client = MongoClients.create(uri);

/*
    Prereq: Create collections. CRUD operations in transactions must be on existing collections.
 */
// 事務不會創建表,所以一定要保證表的存在
client.getDatabase("mydb1").getCollection("foo")
        .withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("abc", 0));
client.getDatabase("mydb2").getCollection("bar")
        .withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("xyz", 0));

/* Step 1: Start a client session. */
// 事務的第一步
final ClientSession clientSession = client.startSession();

/* Step 2: Optional. Define options to use for the transaction. */
// 可選項,對事務的讀寫安全級別進行設置
// WriteConcern.MAJORITY 要求已寫入到副本集中的大多數服務器中
// ReadConcern.LOCAL 從實例返回數據,但不能保證數據已被寫入大多數副本集成員(即可以回滾)。
// 事務 從最近的節點(哪怕支持回滾的節點)中返回數據。
// 對於分片羣集上的事務 不保證來自分片上的同一快照。
TransactionOptions txnOptions = TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();

/* Step 3: Define the sequence of operations to perform inside the transactions. */
// 定義在事務內的順序操作
TransactionBody txnBody = new TransactionBody<String>() {
    public String execute() {
        MongoCollection<Document> coll1 = client.getDatabase("mydb1").getCollection("foo");
        MongoCollection<Document> coll2 = client.getDatabase("mydb2").getCollection("bar");

        /*
           Important:: You must pass the session to the operations.
         */
        coll1.insertOne(clientSession, new Document("abc", 1));
        coll2.insertOne(clientSession, new Document("xyz", 999));
        return "Inserted into collections in different databases";
    }
};
try {
    /*
       Step 4: Use .withTransaction() to start a transaction,
       execute the callback, and commit (or abort on error).
    */
  // 執行事務
    clientSession.withTransaction(txnBody, txnOptions);
} catch (RuntimeException e) {
    // some error handling
} finally {
    clientSession.close();
}

事務的Java代碼示例:
https://docs.mongodb.com/manual/core/transactions/#transactions-api

一、當一個事務寫入多個分片時,並非所有外部讀取操作都需要等待已提交事務的結果在所有分片上可見。
例如,如果提交了一個事務,並且在分片A上可以看到寫1,
但是在分片B上還看不到寫2,則外部讀的安全級別設置爲“local,那麼可以讀取寫1的結果而看不到寫2。

二、在大多數情況下,與單文檔寫入相比,多文檔事務產生的性能成本更高,並且多文檔事務的可用性不應代替有效的schema設計。
在許多情況下,非規範化數據模型(嵌入式文檔和數組)對於我們的數據和用例依舊是最佳的。
也就是說,在許多情況下,對數據進行適當的建模將最大程度地減少對多文檔事務的需求。

存儲引擎

關鍵特性 MMAPV1 wiredTiger
簡介和默認引擎 MongoDB從零開始引入,默認引擎到3.0版本。在4.0中已棄用,將來會刪除 在3.0版本中引入,從3.2版本開始默認
資料壓縮 不支持壓縮 使用默認的snappy壓縮方法和zlib壓縮方法進行壓縮。因此佔用的空間少於MMAPV1引擎
日誌記錄 MongoDB首先將內存更改寫入磁盤日誌文件.如果在將更改提交到數據文件之前MongoDB關閉/終止,則MongoDB可以使用日誌文件將寫操作應用於數據文件並保持一致的狀態。 WiredTiger日記保留檢查點之間的所有數據修改。如果MongoDB在檢查點之間退出,它將使用日誌重播自上一個檢查點以來修改的所有數據。
鎖與併發 直到2.6,MongoDB都使用了readers-writer [1]鎖,該鎖允許對數據庫的併發讀取訪問,但允許對單個寫入操作的獨佔訪問。從3.0開始,使用收集級別鎖定 它支持文檔級鎖定。
事務 對單個文檔的操作是原子的 多文檔事務僅適用於4.0版以上的部署
CPU 性能 添加CPU內核不會顯着提高性能 在多核系統上表現更好
加密 不能加密 MongoDB企業版和PSMDB 3.6.8中的BETA均可使用靜態加密。
內存 自動使用計算機上的所有可用內存作爲其緩存 使用內部緩存和文件系統緩存
更新 它在具有大量插入,讀取和就地更新的工作負載方面表現出色。 不支持就地更新。它導致整個文檔被重寫
可調性 調整的機會更少 允許通過不同的變量對此引擎進行更多調整。例如:緩存大小,讀/寫票證,檢查點間隔等

參考地址:https://www.percona.com/blog/2019/01/03/mongodb-engines-mmapv1-vs-wiredtiger/

WiredTiger and in-place updates

簡單理解:
更新一條記錄時:
①在原有的基礎上更新
②先刪除再新增

①的方式就是 in-place updates。

https://stackoverflow.com/questions/49596247/wiredtiger-and-in-place-updates

常見問題

Sort operation used more than the maximum 33554432 bytes of RAM

因爲 mongo 的 sort 操作是在內存中操作的,必然會佔據內存,同時mongo 內的一個機制限制排序時最大內存爲 32M。
解決辦法就是創建索引。

正常情況下一次查詢使用一個索引,$or 查詢是個例外

db.foo.find({"$or":[{'x':123},{"y":456}]})

創建索引時,一定要後臺執行

db.people.ensureIndex({x:1,y:1},{background:1})

數據量很大的情況下,比如8千萬條數據,不加backgroud:true或1整個集羣就卡死。

在數據庫建立索引時,默認時 “foreground” 也就是前臺建立索引,但是,當你的數據庫數據量很大時,在建立索引的時會讀取數據文件,大量的文件讀寫會阻止其他的操作。

深層次翻頁問題

公司有個業務,查詢的數據量很多,比如我要查詢2007-2018年的數據,總共有98萬多條數據。
而我公司的交互,又是支持點擊最後一頁,這樣就會造成數據庫skip數據量很大,導致查詢速度非常慢,大概是10秒到13秒的樣子(已經建好了,最優的索引);
在這裏插入圖片描述

參考地址:
https://stackoverflow.com/questions/49596247/wiredtiger-and-in-place-updates

https://www.percona.com/blog/2019/01/03/mongodb-engines-mmapv1-vs-wiredtiger

https://cloud.tencent.com/developer/article/1168436

http://bsonspec.org/spec.html

https://stackoverflow.com/questions/12438280/what-is-bson-and-exactly-how-is-it-different-from-json

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章