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
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...