MongoDB基礎操作

来源:https://www.cnblogs.com/misakivv/p/18159503
-Advertisement-
Play Games

目錄一、什麼是MongoDB二、MongoDB 與關係型資料庫對比三、數據類型四、部署MongoDB1、下載二進位包2、下載安裝包並解壓3、創建用於存放數據和日誌的目錄,並修改許可權4、啟動MongoDB4.1前臺啟動4.2後臺啟動4.3、配置文件啟動服務4.4、配置systemd服務4.5、syst ...


目錄

一、什麼是MongoDB

MongoDB 是一個開源、高性能、無模式的、基於分散式文件存儲的文檔型資料庫,當初的設計就是用於簡化開發和方便擴展,是 NoSQL 資料庫產品中的一種。是最像關係型資料庫(MySQL)的非關係型資料庫。

它支持的數據結構非常鬆散,是一種類似於JSON的格式叫BSON(Binary JSON),所以它既可以存儲比較複雜的數據類型,又相當的靈活。

二、MongoDB 與關係型資料庫對比

webp

SQL 術語/概念 MongoDB 術語/概念 解釋說明
database database 資料庫
table collection 資料庫表/集合
row document 數據記錄行/文檔
column field 數據欄位/域
index index 索引
table joins 不支持 表連接,MongoDB 不支持
不支持 嵌入文檔 MongoDB 通過嵌入式文檔來替代多表連接
primary key primary key 主鍵,MongoDB 自動將_id 欄位設置為主鍵

三、數據類型

數據類型 描述 舉例
字元串 utf8字元串都可以表示為字元串類型的數據
對象id 對象id是文檔的12位元組的唯一ID
布爾值 真或者假:true或者false
數組 值的集合或者列表都可以表示成數組
整數 (Int32 Int64 你們就知道有個Int就行了,一般我們用Int32)
null 表示空值或者未定義的對象
undefined 文檔中也可以使用未定義類型

四、部署MongoDB

1、下載二進位包

下載地址

image-20240424165506053

2、下載安裝包並解壓

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.6.tgz
tar xzvf mongodb-linux-x86_64-rhel70-4.4.6.tgz -C /usr/local
cd /usr/local/
ln -s /usr/local/mongodb-linux-x86_64-rhel70-4.4.6 /usr/local/mongodb

3、創建用於存放數據和日誌的目錄,並修改許可權

# 創建存放數據的目錄
mkdir -p /usr/local/mongodb/data/db
# 創建存放日誌的目錄
mkdir -p /usr/local/mongodb/logs
# 創建日誌記錄文件
touch /usr/local/mongodb/logs/mongodb.log

4、啟動MongoDB

4.1前臺啟動

MongoDB的預設啟動方式為前臺啟動

cd /usr/local/mongodb/

bin/mongod \
--dbpath /usr/local/mongodb/data/db/ \
--logpath /usr/local/mongodb/logs/mongodb.log \
--logappend \
--port 27017 \
--bind_ip 0.0.0.0

參數解釋:

 --dbpath:指定數據文件存放目錄
 --logpath:指定日誌文件,註意是指定文件不是目錄
 --logappend:使用追加的方式記錄日誌
 --port:指定埠,預設為 27017
 --bind_ip:綁定服務 IP,若綁定 127.0.0.1,則只能本機訪問,預設為本機地址

4.2後臺啟動

後臺啟動在命令中添加--fork即可

cd /usr/local/mongodb/

bin/mongod \
--dbpath /usr/local/mongodb/data/db/ \
--logpath /usr/local/mongodb/logs/mongodb.log \
--logappend \
--port 27017 \
--bind_ip 0.0.0.0 \
--fork

4.3、配置文件啟動服務

bin目錄下增加一個mongodb.conf配置文件

vim /usr/local/mongodb/bin/mongodb.conf
# 數據文件存放目錄
dbpath = /usr/local/mongodb/data/db
# 日誌文件存放目錄
logpath = /usr/local/mongodb/logs/mongodb.log
# 以追加的方式記錄日誌
logappend = true
# 埠預設為 27017
port = 27017
# 對訪問 IP 地址不做限制,預設為本機地址
bind_ip = 0.0.0.0
# 以守護進程的方式啟用,即在後臺運行
fork = true

image-20240424171746978

啟動命令:

bin/mongod -f /usr/local/mongodb/bin/mongodb.conf

image-20240424172044021

4.4、配置systemd服務

vim /usr/lib/systemd/system/mongodb.service

[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target 
[Service] 
Type=forking 
ExecStart=/usr/local/mongodb/bin/mongod --config /usr/local/mongodb/bin/mongodb.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/usr/local/mongodb/bin/mongod --shutdown --config /usr/local/mongodb/bin/mongodb.conf
PrivateTmp=true 
[Install] 
WantedBy=multi-user.target

chmod 754 /usr/lib/systemd/system/mongodb.service

4.5、systemctl啟動MongoDB

systemctl start mongodb

5、客戶端配置

添加環境變數

echo "export PATH=/usr/local/mongodb/bin/:$PATH" >> /etc/profile
source /etc/profile
mongo

6、關閉MongoDB

6.1、前臺啟動

Ctrl + c

6.2、後臺啟動

# 命令啟動方式的關閉
bin/mongod --dbpath /usr/local/mongodb/data/db/ --logpath /usr/local/mongodb/logs/mongodb.log --logappend --port 27017 --bind_ip 0.0.0.0 --fork --shutdown
# 配置文件啟動方式的關閉
bin/mongod -f /usr/local/mongodb/bin/mongodb.conf --shutdown

6.3、kill命令關閉

不推薦使用

# 查看 mongodb 運行的進程信息
ps -ef | grep mongodb
# kill -9 強制關閉
kill -9 pid

6.4、MongoDB函數關閉

# 連接 mongodb
mongo
# 切換 admin 資料庫
use admin
# 執行以下函數(2選1)即可關閉服務
db.shutdownServer()
db.runCommand("shutdown")

五、MongoDB基本操作及增刪改查

1、基本操作

1.1、登錄資料庫

mongo

1.2、查看資料庫

show databases
show dbs

image-20240424183039764

1.3、查看當前正在使用的資料庫

db

image-20240425115609645

1.4、選擇/創建資料庫

use admin

image-20240425114338328

如果切換到一個沒有的資料庫,那麼會隱式創建這個資料庫。(後期當該資料庫有數據時,系統自動創建)

use admin1

image-20240425114612080

1.5、查看集合

show collections

image-20240425114752959

1.6、創建集合

db.createCollection('集合名')

image-20240425115030221

1.7、刪除集合

db.集合名.drop()

image-20240425115744209

1.8、刪除資料庫

通過use語法選擇數據
通過db.dropDataBase()刪除資料庫

> use admin1
switched to db admin1
> show collections
c2
> db.dropDatabase()
{ "dropped" : "admin1", "ok" : 1 }
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

image-20240425120604758

2、增刪改查

2.1、插入文檔

如果集合存在,那麼直接插入數據。

如果集合不存在,那麼會隱式創建。

db.集合名.insert(JSON數據)
  • 在test1資料庫的c1集合中插入文檔,(姓名:張三,年齡:18)
> use test1
switched to db test1
> show collections
> db.createCollection('c1')
{ "ok" : 1 }
> db.c1.insert({name:"張三",age:18})
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三", "age" : 18 }

image-20240425125211753

  • 資料庫和集合不存在都隱式創建
  • 對象的鍵統一不加引號(方便看),但是查看集合數據時系統會自動加
  • mongodb會給每條數據增加一個全球唯一的_id
2.1.1、一次性插入多條數據
  • 數組中一個個寫入json數據
> db.c1.insert([{name:"李四",age:20},{name:"王五",age:21},{name:"趙六",age:22}])
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 3,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "趙六", "age" : 22 }

image-20240425125249398

  • 寫for迴圈插入數據
> for (var i=1;i<=10;i++) {db.c1.insert({name:"a"+i , age: i}) }
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "趙六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1", "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2", "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3", "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4", "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5", "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6", "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425125400607

2.2、查詢文檔

db.集合名.find(條件[,查詢的列])
條件 寫法
查詢所有的數據 {}或者不寫
查詢age=6的數據
既要age=6又要性別=男
查詢的列(可選參數) 寫法
查詢全部列(欄位) 不寫
只顯示age列(欄位)
除了age列(欄位)都顯示

其他語法

db.集合名.find({
            鍵:{運算符:值}
            })
運算符 作用
$gt 大於
$gte 大於等於
$lt 小於
$lte 小於等於
$ne 不等於
$in in
$nin not in
  • 查看所有數據
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "趙六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1", "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2", "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3", "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4", "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5", "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6", "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425125449664

  • 只看name列
> db.c1.find({},{name:1})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三" }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四" }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五" }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "趙六" }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1" }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2" }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3" }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4" }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5" }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6" }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7" }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8" }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9" }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10" }

image-20240425125526995

  • 查看除了name列
> db.c1.find({},{name:0})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "age" : 10 }

image-20240425125554132

  • 查詢age大於6的數據
> db.c1.find({age:{$gt:6}})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "趙六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425125634325

  • 查詢年齡為7歲、10歲、18歲的數據
> db.c1.find({age:{$in:[7,10,18]}})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "張三", "age" : 18 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425142853007

2.2.1、查詢集合內所有的記錄數
db.集合名.count()

image-20240425205417337

2.3、修改文檔

db.集合名.update(
  <filter>,          // 查詢條件(篩選待更新的文檔)
  <update>,          // 更新操作定義(如何修改文檔)
  {
    upsert: <boolean>,  // 可選,如果無匹配文檔則插入,預設為 false
    multi: <boolean>,   // 可選,是否更新所有匹配的文檔,預設為 false(僅更新第一條)
    collation: <object>, // 可選,指定比較選項(如大小寫敏感等)
    arrayFilters: <array>, // 可選,用於處理嵌套數組中的條件匹配
    hint: <string|document>, // 可選,提供索引來指導查詢
    writeConcern: <document>, // 可選,指定寫關註級別
    let: <object> // 可選,用於與聚合管道更新相關的變數定義
  }
)
  • {name:"張三"}修改為{name:"zhangsan"}
> db.c1.update({name:"張三"},{$set:{name:"zhangsan"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "zhangsan", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "趙六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1", "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2", "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3", "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4", "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5", "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6", "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425184009386

  • {name:"李四"}的年齡加/減5

年齡加5

db.c1.update({name:"李四"},{$inc:{age:5}})

image-20240425184419154

年齡減5

db.c1.update({name:"李四"},{$inc:{age:-5}})

image-20240425184616300

2.4、刪除文檔

db.集合名.remove(條件[,是否刪除一條])
  • 刪除一條數據

    • db.c1.remove({},true)
      

      預設刪除的第一條數據

      image-20240425204653851

    • db.c1.remove({name:"李四"})
      

      刪除指定數據

      image-20240425204856853

六、MongoDB支持存儲的數據類型

1、數字

  • shell預設使用64位浮點型數值
db.b1.insert({x:3.1415926})
db.b1.insert({x:3})

image-20240425213512686

  • 整型值,可以用NumberInt或者NumberLong表示
db.b1.insert({x:NumberInt(10)})
db.b1.insert({x:NumberLong(12)})

image-20240425213843340

2、字元串

db.b1.insert({x:"hello MongoDB!"})

image-20240425214353152

3、正則表達式

查詢所有keyx,valuehello開頭的文檔且不區分大小寫

db.b1.find({x:/^(hello).(.[a-zA-Z0-9])+/i})

image-20240425214936289

4、數組

數組中的數據類型可以是多種多樣的

db.b1.insert({x:[1,2,3,4,new Date()]})

image-20240425215940415

5、日期

db.b1.insert({x:new Date()})

image-20240425220308105

6、內嵌文檔

一個文檔也可以作為另一個文檔的value

db.b1.insert({name:"三國演義",author:{name:"羅貫中",age:70}})

image-20240425221008151

七、MongoDB中的索引

1、查看索引

預設情況下,集合中的_id欄位就是索引,我們可以通過getIndexes()方法來查看一個集合中的索引:

db.b1.getIndexes()

image-20240425222309926

  1. v: 表示索引版本。在這個例子中,值為 2,表示這是一個版本 2 的索引。索引版本通常由 MongoDB 內部管理,用戶通常不需要直接關心。
  2. key: 描述了索引的鍵(即排序依據)。鍵是一個對象,鍵名為欄位名,鍵值為排序方向。在給出的例子中,{ "_id" : 1 } 表示索引基於欄位 _id,且按升序(1)排序。在 MongoDB 中,每個集合都預設有一個名為 _id 的主鍵索引,它是唯一的,並且總是按升序排列。
  3. name: 指定索引的名稱。這裡為 "name" : "_id_",表示這是一個針對 _id 欄位的索引,其名稱預設為 _id_。在 MongoDB 中,主鍵索引的名稱通常是固定的,即 _id_

2、需要索引的查詢場景

2.1、創建有10000個文檔的集合

for (var i=1;i<=10000;i++) {db.q1.insert({name:"test"+i , age: i})}
db.q1.count()

image-20240426082844602

2.2、查詢age200的文檔

db.q1.find({age:200})

image-20240425230647795

這種查詢預設情況下會做全表掃描,可以用explain()來查看一下查詢計劃

db.q1.find({age:200}).explain("executionStats")
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "test3.q1",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "age" : {
                                "$eq" : 200
                        }
                },
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "age" : {
                                        "$eq" : 200
                                }
                        },
                        "direction" : "forward"
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 2,
                "totalKeysExamined" : 0,
                "totalDocsExamined" : 10000,
                "executionStages" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "age" : {
                                        "$eq" : 200
                                }
                        },
                        "nReturned" : 1,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 10002,
                        "advanced" : 1,
                        "needTime" : 10000,
                        "needYield" : 0,
                        "saveState" : 10,
                        "restoreState" : 10,
                        "isEOF" : 1,
                        "direction" : "forward",
                        "docsExamined" : 10000
                }
        },
        "serverInfo" : {
                "host" : "localhost.localdomain",
                "port" : 27017,
                "version" : "4.4.6",
                "gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"
        },
        "ok" : 1
}

queryPlanner 部分

  • plannerVersion: 表示查詢優化器的版本。
  • namespace: 查詢涉及的集合名,即 test3.q1
  • indexFilterSet: 若為 true,表示查詢使用了索引過濾器;此處為 false,說明沒有使用。
  • parsedQuery: 顯示解析後的查詢條件,即查找 age 欄位等於 200 的文檔。
  • winningPlan: 描述被選擇的執行計劃。在這個案例中,執行計劃的 stage"COLLSCAN",意味著進行了全集合掃描(Collection Scan)。這意味著為了找到匹配的文檔,MongoDB 需要遍歷整個 q1 集合,對每個文檔應用 filter 中指定的條件(age: { $eq: 200 })。
  • rejectedPlans: 空數組,表示沒有其他備選執行計劃被否決。如果有多個可行計劃,MongoDB 會選擇成本最低的一個作為 winningPlan,其餘的則記錄在此處。

executionStats 部分

這部分提供了實際執行查詢時的統計信息:

  • executionSuccess: 指示查詢是否成功完成,true 表示成功。
  • nReturned: 返回的文檔數量,這裡是 1,說明找到了一個年齡為 200 的文檔。
  • executionTimeMillis: 執行查詢所花費的時間(毫秒),本例中為 2 毫秒。
  • totalKeysExamined: 查看的索引鍵數量。由於未使用索引,此處為 0
  • totalDocsExamined: 查看的文檔數量,即全集合掃描過程中檢查過的文檔總數,這裡為 10000,表明集合中有 10000 個文檔被逐一檢查以找出符合 age: 200 的文檔。
  • executionStages: 提供了更多關於執行階段的細節,與 winningPlan 相對應。這裡再次確認了進行了全集合掃描(COLLSCAN),並且實際查看了 10000 個文檔 (docsExamined) 才找到 1 個匹配的文檔 (nReturned).

serverInfo 部分

  • 提供了運行 MongoDB 伺服器的主機名、埠、版本號以及 Git 版本信息。

ok

  • 值為 1,表示命令執行成功。

2.3、添加limit查詢文檔

db.q1.find({age:10}).limit(20)

db.q1.find({age:10}).limit(20).explain("executionStats")
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "test3.q1",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "age" : {
                                "$eq" : 10
                        }
                },
                "winningPlan" : {
                        "stage" : "LIMIT",
                        "limitAmount" : 20,
                        "inputStage" : {
                                "stage" : "COLLSCAN",
                                "filter" : {
                                        "age" : {
                                                "$eq" : 10
                                        }
                                },
                                "direction" : "forward"
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 4,
                "totalKeysExamined" : 0,
                "totalDocsExamined" : 10000,
                "executionStages" : {
                        "stage" : "LIMIT",
                        "nReturned" : 1,
                        "executionTimeMillisEstimate" : 1,
                        "works" : 10002,
                        "advanced" : 1,
                        "needTime" : 10000,
                        "needYield" : 0,
                        "saveState" : 10,
                        "restoreState" : 10,
                        "isEOF" : 1,
                        "limitAmount" : 20,
                        "inputStage" : {
                                "stage" : "COLLSCAN",
                                "filter" : {
                                        "age" : {
                                                "$eq" : 10
                                        }
                                },
                                "nReturned" : 1,
                                "executionTimeMillisEstimate" : 1,
                                "works" : 10002,
                                "advanced" : 1,
                                "needTime" : 10000,
                                "needYield" : 0,
                                "saveState" : 10,
                                "restoreState" : 10,
                                "isEOF" : 1,
                                "direction" : "forward",
                                "docsExamined" : 10000
                        }
                }
        },
        "serverInfo" : {
                "host" : "localhost.localdomain",
                "port" : 27017,
                "version" : "4.4.6",
                "gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"
        },
        "ok" : 1
}

可以明顯感受到加了limit後查詢速度變快了很多

但是如果我們查詢age9999的文檔那麼還是得全表掃描一遍

此時我們就可以給該欄位加上索引

2.4、創建索引

db.collection.createIndex(keys, options)

參數:

  • keys:

    • 包含欄位和值對的文檔,其中欄位是索引鍵,描述該欄位的索引類型
    • 對於欄位的上升索引,請指定為1,對於降序指定為-1
  • options:

    • 可選,包含一組控制索引創建的選項的文檔
    選項 類型 描述
    background 布爾 是否在後臺執行創建索引的過程,不阻塞對集合的操作false【預設】
    unique 布爾 是否創建具有唯一性的索引 false【預設】
    name 字元串 自定義索引名稱,如果不指定,mongodb將通過 下劃線 連接 索引欄位的名稱和排序規則 生成一個索引名稱。一旦創建不能修改,只能刪除再重新創建
    partialFilterExpression Document 僅為集合中符合條件的文檔建立索引,降低創建和維護成本
    sparse 布爾 僅為集合中具有指定欄位的文檔建立索引 false 【預設】
    expireAfterSeconds integer單位 秒 用於 TTL 索引中 控制 文檔保存在集合中的時間
    storageEngine Document 指定存儲引擎配置
db.q1.ensureIndex({age:1})

查看查詢計劃

db.q1.find({age:200}).explain("executionStats")
> db.q1.find({age:200}).explain("executionStats")
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "test3.q1",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "age" : {
                                "$eq" : 200
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "age" : 1
                                },
                                "indexName" : "age_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "age" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "age" : [
                                                "[200.0, 200.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 1,
                "totalKeysExamined" : 1,
                "totalDocsExamined" : 1,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 1,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 2,
                        "advanced" : 1,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 0,
                        "restoreState" : 0,
                        "isEOF" : 1,
                        "docsExamined" : 1,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 1,
                                "executionTimeMillisEstimate" : 0,
                                "works" : 2,
                                "advanced" : 1,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 0,
                                "restoreState" : 0,
                                "isEOF" : 1,
                                "keyPattern" : {
                                        "age" : 1
                                },
                                "indexName" : "age_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "age" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "age" : [
                                                "[200.0, 200.0]"
                                        ]
                                },
                                "keysExamined" : 1,
                                "seeks" : 1,
                                "dupsTested" : 0,
                                "dupsDropped" : 0
                        }
                }
        },
        "serverInfo" : {
                "host" : "localhost.localdomain",
                "port" : 27017,
                "version" : "4.4.6",
                "gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"
        },
        "ok" : 1
}
  • executionTimeMillis:執行耗時 1 毫秒。

  • totalKeysExaminedtotalDocsExamined:分別檢查了 1 個索引鍵和 1 個文檔。由於使用了覆蓋索引(即索引包含了查詢所需的所有欄位),這裡的兩個值相等,意味著無需額外查詢文檔。

查看索引

> db.q1.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "age" : 1
                },
                "name" : "age_1"
        }
]

image-20240426093010417

2.5、自定義索引名字

db.q1.ensureIndex({name:1},{name:"MyNameIndex"})

image-20240426102603193

3、查看索引的大小

預設單位是位元組

db.q1.totalIndexSize()

image-20240426102044812

4、刪除索引

4.1、按名稱刪除索引

db.q1.dropIndex("MyNameIndex")

image-20240426102841487

4.2、刪除所有的索引

db.q1.dropIndexes()

image-20240426103015481

5、優缺點

5.1、優點:

  • 提高查詢性能:索引能夠大大加快數據查詢速度,特別是對於含有複雜查詢條件、排序、分組或聚合操作的查詢。
  • 支持高效排序:當查詢需要對特定欄位進行排序時,如果該欄位有索引,MongoDB可以直接利用索引來完成排序,避免了大量數據的內部排序操作,顯著提升性能。
  • 覆蓋查詢:如果一個索引包含了查詢所需的全部欄位,稱為“覆蓋索引”。在這種情況下,MongoDB可以直接從索引中獲取所有數據,而無需訪問實際文檔,從而減少磁碟I/O操作,提高查詢效率。
  • 唯一性約束:創建唯一索引可以確保指定欄位的值在整個集合中唯一,防止插入重覆數據,確保數據完整性。

5.2、缺點:

  • 占用存儲空間:索引需要額外的存儲空間來保存索引數據結構。隨著數據量的增長和索引數量的增加,存儲開銷會逐漸增大。需要根據實際業務需求權衡查詢性能與存儲成本。
  • 寫操作性能影響:插入、更新和刪除文檔時,不僅要修改原數據,還要同步更新相關索引。對於寫密集型應用,大量的索引可能導致寫操作性能下降,尤其是當索引較多或索引欄位頻繁變動時。
  • 索引維護成本:隨著數據的變化,索引需要不斷維護和更新。對於大型數據集,索引重建可能需要消耗較長時間和系統資源。此外,隨著業務發展,可能需要定期評估和調整索引策略,以適應新的查詢模式。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目: ​ 設計一個進位轉換程式,使用順序棧設計一個把十進位數轉換為十六進位數的介面,實現當通過鍵盤輸入一個非負的十進位數,可以在終端輸出對應的十六進位數。 例如: 100 --> 0x64 --> 100%16 = 4 --> 100/16 = 6 6%16 = 6 題目分析: ​ 該題需要對用戶 ...
  • 棧(stack) 原理說明: ​ 學習數據結構的目的是為了更好的處理和存儲數據,對於順序表而言改查比較容易,增刪比較麻煩,對於鏈式表而言,增刪比較簡單,改查比較麻煩,所以每種數據結構都有不同的特點,用戶需要選擇合適的數據結構。 ​ 棧記憶體自頂向下進行遞增,其實棧和順序表以及鏈式表都一樣,都屬於線性結 ...
  • Kafka通過一系列機制來確保數據不丟失,這些機制涵蓋了生產者、Broker和消費者等關鍵環節。以下是Kafka保證數據不丟失的主要方式: 生產者生產數據不丟失: 同步方式:生產者發送數據給Kafka後,會等待Kafka的確認。如果在一定時間內(如10秒)沒有收到Broker的ack響應,生產者會認 ...
  • 聲明: 以下內容為個人筆記,內容不完全正確,請謹慎參考。 文本處理工具 cut: cut 工作是“剪”,具體來說就是在文件中負責剪切數據。cut 命令從文件的每個行剪切位元組、字元和欄位輸出。 1、基本語法: cut [選項參數] filename 說明:預設分隔符是副表符 2、選項參數說明 選項參數 ...
  • 雙向迴圈鏈表 原理與應用 雙向迴圈鏈表與雙向鏈表的區別:指的是雙向迴圈鏈表的首結點中的prev指針成員指向鏈表的尾結點,並且雙向迴圈鏈表的尾結點里的next指針成員指向鏈表的首結點,所以雙向迴圈鏈表也屬於環形結構。 雙向迴圈鏈表各功能實現 (1)為了管理雙向迴圈鏈表,需要構造頭結點的數據類型以及構造 ...
  • 1.綜述 本文以HiveSQL語法進行代碼演示。 對於其他資料庫來說同樣也適用,比如SparkSQL,FlinkSQL以及Mysql8,Oracle,SqlServer等傳統的關係型資料庫。 已更新第一類聚合函數類,點擊這裡閱讀 ①SQL視窗函數系列一之聚合函數類 ②SQL視窗函數系列二之分組排序窗 ...
  • 隨著企業數據規模的增長和業務多元化發展,海量數據實時、多維地靈活查詢變成業務常見訴求。同時多套資料庫系統成為常態,這既帶來了數據管理的複雜性,又加大了數據使用的難度,面對日益複雜的數據環境和嚴格的數據安全要求,需要解決多資料庫系統並存、數據孤島嚴重、許可權管理混亂和數據查詢提取困難等問題。與此同時,企 ...
  • Spark 是一個快速、通用、可擴展的大數據計算引擎,具有高性能、易用、容錯、可以與 Hadoop 生態無縫集成、社區活躍度高等優點。在實際使用中,具有廣泛的應用場景: · 數據清洗和預處理:在大數據分析場景下,數據通常需要進行清洗和預處理操作以確保數據質量和一致性,Spark 提供了豐富的 API ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...