- 一、什麼是MongoDB
- 二、MongoDB 與關係型資料庫對比
- 三、資料型別
- 四、部署MongoDB
- 1、下載二進位制包
- 2、下載安裝包並解壓
- 3、建立用於存放資料和日誌的目錄,並修改許可權
- 4、啟動MongoDB
- 4.1前臺啟動
- 4.2後臺啟動
- 4.3、配置檔案啟動服務
- 4.4、配置systemd服務
- 4.5、systemctl啟動MongoDB
- 5、客戶端配置
- 6、關閉MongoDB
- 6.1、前臺啟動
- 6.2、後臺啟動
- 6.3、kill命令關閉
- 6.4、MongoDB函式關閉
- 五、MongoDB基本操作及增刪改查
- 1、基本操作
- 1.1、登入資料庫
- 1.2、檢視資料庫
- 1.3、檢視當前正在使用的資料庫
- 1.4、選擇/建立資料庫
- 1.5、檢視集合
- 1.6、建立集合
- 1.7、刪除集合
- 1.8、刪除資料庫
- 2、增刪改查
- 2.1、插入文件
- 2.1.1、一次性插入多條資料
- 2.2、查詢文件
- 2.2.1、查詢集合內所有的記錄數
- 2.3、修改文件
- 2.4、刪除文件
- 2.1、插入文件
- 1、基本操作
- 六、MongoDB支援儲存的資料型別
- 1、數字
- 2、字串
- 3、正規表示式
- 4、陣列
- 5、日期
- 6、內嵌文件
- 七、MongoDB中的索引
- 1、檢視索引
- 2、需要索引的查詢場景
- 2.1、建立有10000個文件的集合
- 2.2、查詢
age
為200
的文件 - 2.3、新增
limit
查詢文件 - 2.4、建立索引
- 2.5、自定義索引名字
- 3、檢視索引的大小
- 4、刪除索引
- 4.1、按名稱刪除索引
- 4.2、刪除所有的索引
- 5、優缺點
- 5.1、優點:
- 5.2、缺點:
一、什麼是MongoDB
MongoDB
是一個開源、高效能、無模式的、基於分散式檔案儲存的文件型資料庫,當初的設計就是用於簡化開發和方便擴充套件,是 NoSQL
資料庫產品中的一種。是最像關係型資料庫(MySQL
)的非關係型資料庫。
它支援的資料結構非常鬆散,是一種類似於JSON
的格式叫BSON(Binary JSON)
,所以它既可以儲存比較複雜的資料型別,又相當的靈活。
二、MongoDB 與關係型資料庫對比
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、下載二進位制包
下載地址
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
啟動命令:
bin/mongod -f /usr/local/mongodb/bin/mongodb.conf
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
1.3、檢視當前正在使用的資料庫
db
1.4、選擇/建立資料庫
use admin
如果切換到一個沒有的資料庫,那麼會隱式建立這個資料庫。(後期當該資料庫有資料時,系統自動建立)
use admin1
1.5、檢視集合
show collections
1.6、建立集合
db.createCollection('集合名')
1.7、刪除集合
db.集合名.drop()
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
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 }
- 資料庫和集合不存在都隱式建立
- 物件的鍵統一不加引號(方便看),但是檢視集合資料時系統會自動加
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 }
- 寫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 }
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 }
- 只看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" }
- 檢視除了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 }
- 查詢
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 }
- 查詢年齡為
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 }
2.2.1、查詢集合內所有的記錄數
db.集合名.count()
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 }
- 將
{name:"李四"}
的年齡加/減5
年齡加5
db.c1.update({name:"李四"},{$inc:{age:5}})
年齡減5
db.c1.update({name:"李四"},{$inc:{age:-5}})
2.4、刪除文件
db.集合名.remove(條件[,是否刪除一條])
-
刪除一條資料
-
db.c1.remove({},true)
預設刪除的第一條資料
-
db.c1.remove({name:"李四"})
刪除指定資料
-
六、MongoDB支援儲存的資料型別
1、數字
shell
預設使用64
位浮點型數值
db.b1.insert({x:3.1415926})
db.b1.insert({x:3})
- 整型值,可以用
NumberInt
或者NumberLong
表示
db.b1.insert({x:NumberInt(10)})
db.b1.insert({x:NumberLong(12)})
2、字串
db.b1.insert({x:"hello MongoDB!"})
3、正規表示式
查詢所有
key
為x
,value
以hello
開頭的文件且不區分大小寫
db.b1.find({x:/^(hello).(.[a-zA-Z0-9])+/i})
4、陣列
陣列中的資料型別可以是多種多樣的
db.b1.insert({x:[1,2,3,4,new Date()]})
5、日期
db.b1.insert({x:new Date()})
6、內嵌文件
一個文件也可以作為另一個文件的
value
db.b1.insert({name:"三國演義",author:{name:"羅貫中",age:70}})
七、MongoDB中的索引
1、檢視索引
預設情況下,集合中的
_id
欄位就是索引,我們可以透過getIndexes()
方法來檢視一個集合中的索引:
db.b1.getIndexes()
v
: 表示索引版本。在這個例子中,值為2
,表示這是一個版本 2 的索引。索引版本通常由 MongoDB 內部管理,使用者通常不需要直接關心。key
: 描述了索引的鍵(即排序依據)。鍵是一個物件,鍵名為欄位名,鍵值為排序方向。在給出的例子中,{ "_id" : 1 }
表示索引基於欄位_id
,且按升序(1)排序。在 MongoDB 中,每個集合都預設有一個名為_id
的主鍵索引,它是唯一的,並且總是按升序排列。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()
2.2、查詢age
為200
的文件
db.q1.find({age:200})
這種查詢預設情況下會做全表掃描,可以用
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
後查詢速度變快了很多但是如果我們查詢
age
為9999
的文件那麼還是得全表掃描一遍此時我們就可以給該欄位加上索引
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 毫秒。
totalKeysExamined 和 totalDocsExamined:分別檢查了 1 個索引鍵和 1 個文件。由於使用了覆蓋索引(即索引包含了查詢所需的所有欄位),這裡的兩個值相等,意味著無需額外查詢文件。
檢視索引
> db.q1.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"age" : 1
},
"name" : "age_1"
}
]
2.5、自定義索引名字
db.q1.ensureIndex({name:1},{name:"MyNameIndex"})
3、檢視索引的大小
預設單位是位元組
db.q1.totalIndexSize()
4、刪除索引
4.1、按名稱刪除索引
db.q1.dropIndex("MyNameIndex")
4.2、刪除所有的索引
db.q1.dropIndexes()
5、優缺點
5.1、優點:
- 提高查詢效能:索引能夠大大加快資料查詢速度,特別是對於含有複雜查詢條件、排序、分組或聚合操作的查詢。
- 支援高效排序:當查詢需要對特定欄位進行排序時,如果該欄位有索引,MongoDB可以直接利用索引來完成排序,避免了大量資料的內部排序操作,顯著提升效能。
- 覆蓋查詢:如果一個索引包含了查詢所需的全部欄位,稱為“覆蓋索引”。在這種情況下,MongoDB可以直接從索引中獲取所有資料,而無需訪問實際文件,從而減少磁碟I/O操作,提高查詢效率。
- 唯一性約束:建立唯一索引可以確保指定欄位的值在整個集合中唯一,防止插入重複資料,確保資料完整性。
5.2、缺點:
- 佔用儲存空間:索引需要額外的儲存空間來儲存索引資料結構。隨著資料量的增長和索引數量的增加,儲存開銷會逐漸增大。需要根據實際業務需求權衡查詢效能與儲存成本。
- 寫操作效能影響:插入、更新和刪除文件時,不僅要修改原資料,還要同步更新相關索引。對於寫密集型應用,大量的索引可能導致寫操作效能下降,尤其是當索引較多或索引欄位頻繁變動時。
- 索引維護成本:隨著資料的變化,索引需要不斷維護和更新。對於大型資料集,索引重建可能需要消耗較長時間和系統資源。此外,隨著業務發展,可能需要定期評估和調整索引策略,以適應新的查詢模式。