linux系統mongdb基礎(1)
阿新 • • 發佈:2020-08-19
mongoDB學習
一、NoSQL介紹
1.NoSQL 簡介
NoSQL(NoSQL = Not Only SQL ),意即"不僅僅是SQL",指的是非關係型的資料庫,是對不同於傳統的關係型資料庫的資料庫管理系統的統稱。 在現代的計算系統上每天網路上都會產生龐大的資料量。 這些資料有很大一部分是由關係資料庫管理系統(RDMBSs)來處理,也有一部分使用非系型資料庫處理 對NoSQL最普遍的解釋是"非關聯型的",強調Key-Value Stores和文件資料庫的優點,而不是單純的反對RDBMS。 NoSQL用於超大規模資料的儲存。(例如谷歌或Facebook每天為他們的使用者收集萬億位元的資料)。這些型別的資料儲存不需要固定的模式,無需多餘操作就可以橫向擴充套件。
2.為什麼使用NoSQL
關係型資料庫對資料要求嚴格,而非關係型資料庫沒有那麼嚴格,對於大量不同欄位的資料,儲存更加方便
二、MongoDB簡介
Mongodb由C++語言編寫的,是一個基於分散式檔案儲存的開源資料庫系統。是專為可擴充套件性,高效能和高可用性而設計的資料庫, 是非關係型資料庫中功能最豐富,最像關係型資料庫的,它支援的資料結構非常散,是類似 json 的 bjson 格式,因此可以儲存比較複雜的資料型別。 MongoDB的(來自於英文單詞“Humongous”,中文含義為“龐大”)是可以應用於各種規模的企業,各個行業以及各類應用程式的開源資料庫。作為一個適用於敏捷開發的資料庫,MongoDB的的資料模式可以隨著應用程式的發展而靈活地更新。 MongoDB 以一種叫做 BSON(二進位制 JSON)的儲存形式將資料作為文件儲存。具有相似結構的文件通常被整理成集合。可以把這些集合看成類似於關係資料庫中的表: 文件和行相似, 欄位和列相似。 json格式:{key:value,key:value} bjson格式:{key:value,key:value} #區別在於:對於資料{id:1},在JSON的儲存上1只使用了一個位元組,而如果用BJSON,那就是至少4個位元組
1.MySQL與mongoDB對比
1)結構對比
mysql | MongoDB |
---|---|
庫 | 庫 |
表 | 集合 |
欄位 | 鍵值 |
行 | 文件 |
1)資料庫中資料(student庫,user表)
uid | name | age |
---|---|---|
1 | zhangyu | 18 |
2 | chencgheng | 28 |
2)mongoDB中的資料(student庫,user集合)
1) {uid:1,name:zhangyu,age:18}
2) {uid:2,name:chencgheng,age:28}
3)區別總結
1.資料結構不同 2.資料庫新增不存在欄位的資料時報錯 3.mongoDB可以新增不存在的欄位的資料 4.mongoDB不需要提前建立好庫和表,建立資料直接會幫助我們建立好
2.MongoDB 特點
1.高效能:
Mongodb 提供高效能的資料永續性,索引支援更快的查詢
2.豐富的語言查詢:
Mongodb 支援豐富的查詢語言來支援讀寫操作(CRUD)以及資料彙總
3.高可用性:
Mongodb 的複製工具,成為副本集,提供自動故障轉移和資料冗餘,
4.水平可擴充套件性:
Mongodb 提供了可擴充套件性,作為其核心功能的一部分,分片是將資料分在一組計算機上。
5.支援多種儲存引擎:
WiredTiger儲存引擎和、 MMAPv1儲存引擎和 InMemory 儲存引擎
3.0以上版本 3.0以下版本
新的引擎壓縮比特別大,原來100個G,可能升級之後所有資料都在,只佔用10個G
6.強大的索引支援:
地理位置索引可用於構建 各種 O2O 應用、文字索引解決搜尋的需求、TTL索引解決歷史資料自動過期的需求
3.MongoDB應用場景
1.遊戲場景:
使用 MongoDB 儲存遊戲使用者資訊,使用者的裝備、積分等直接以內嵌文件的形式儲存,方便查詢、更新
2.物流場景:
使用 MongoDB 儲存訂單資訊,訂單狀態在運送過程中會不斷更新,以 MongoDB 內嵌陣列的形式來儲存,一次查詢就能將訂單所有的變更讀取出來。
3.社交場景:
使用 MongoDB 儲存儲存使用者資訊,以及使用者發表的朋友圈資訊,通過地理位置索引實現附近的人、地點等功能
將送快遞騎手、快遞商家的資訊(包含位置資訊)儲存在 MongoDB,然後通過 MongoDB 的地理位置查詢,這樣很方便的實現了查詢附近的商家、騎手等功能,使得快遞騎手能就近接單
地圖軟體、打車軟體、外賣軟體,MongoDB強大的地理位置索引功能使其最佳選擇
4.物聯網場景:
使用 MongoDB 儲存所有接入的智慧裝置資訊,以及裝置彙報的日誌資訊,並對這些資訊進行多維度的分析
5.視訊直播:
使用 MongoDB 儲存使用者資訊、禮物資訊等
6.電商場景:
上衣有胸圍,褲子有腰圍,如果用資料庫需要分成兩個庫,如果使用MongoDB都可以存在一起
三、MongoDB安裝部署
0.安裝依賴
[root@redis01 ~]# yum install -y libcurl openssl
1.上傳或下載包
#下載地址:https://www.mongodb.com/download-center/community
[root@redis01 ~]# rz mongodb-linux-x86_64-3.6.13.tgz
2.解壓包
[root@redis01 ~]# tar xf mongodb-linux-x86_64-3.6.13.tgz -C /usr/local/
[root@redis01 ~]# ln -s /usr/local/mongodb-linux-x86_64-3.6.13 /usr/local/mongodb
3.配置
#建立目錄
[root@redis01 ~]# mkdir /server/mongo_27017/{conf,logs,pid,data} -p
#配置
[root@redis01 ~]# vim /server/mongo_27017/conf/mongodb.conf
systemLog:
destination: file
logAppend: true
path: /server/mongo_27017/logs/mongodb.log
storage:
journal:
enabled: true
dbPath: /server/mongo_27017/data
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /server/mongo_27017/pid/mongod.pid
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.91
#配置詳解
#日誌相關
systemLog:
#以檔案格式儲存
destination: file
#每次重啟,不生成新檔案,每次都追加到檔案
logAppend: true
#指定檔案路徑
path: /server/mongo_27017/logs/mongodb.log
#資料部分
storage:
#資料回滾。類似於mysql的undolog
journal:
enabled: true
#資料目錄
dbPath: /server/mongo_27017/data
#預設 false,不適用 inmemory engine
directoryPerDB: true
#儲存引擎
wiredTiger:
#儲存引擎設定
engineConfig:
#想把資料存到快取,快取的大小
cacheSizeGB: 1
#設定一個庫就是一個目錄,關閉就全放到一個目錄下,很亂
directoryForIndexes: true
#壓縮相關
collectionConfig:
blockCompressor: zlib
#索引壓縮(與壓縮一起使用)
indexConfig:
prefixCompression: true
#守護程序的模式
processManagement:
fork: true
#指定pid檔案
pidFilePath: /server/mongo_27017/pid/mongod.pid
#指定埠和監聽地址
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.91
4.啟動
[root@redis01 ~]# /usr/local/mongodb/bin/mongod -f /server/mongo_27017/conf/mongodb.conf
about to fork child process, waiting until server is ready for connections.
forked process: 11547
child process started successfully, parent exiting
#驗證啟動
[root@redis01 ~]# ps -ef | grep mongo
root 11547 1 6 08:48 ? 00:00:00 /usr/local/mongodb/bin/mongod -f /server/mongo_27017/conf/mongodb.conf
5.配置環境變數
[root@redis01 ~]# vim /etc/profile.d/mongo.sh
export PATH="/usr/local/mongodb/bin:$PATH"
[root@redis01 ~]# source /etc/profile
四、mongo登入警告處理
1.警告一
#訪問設定沒有被允許
WARNING: Access control is not enabled for the database.
#解決方式:開啟安全認證
[root@redis01 ~]# vim /server/mongo_27017/conf/mongodb.conf
security:
authorization: enabled
2.警告二
#以root使用者運行了
WARNING: You are running this process as the root user, which is not recommended.
#解決方式:使用普通使用者啟動
1.先關閉mongodb
[root@redis01 ~]# mongod -f /server/mongo_27017/conf/mongodb.conf --shutdown
2.建立mongo使用者
[root@redis01 ~]# useradd mongo
[root@redis01 ~]# echo '123456'|passwd --stdin mongo
Changing password for user mongo.
passwd: all authentication tokens updated successfully.
3.授權目錄
[root@redis01 ~]# chown -R mongo.mongo /usr/local/mongodb/
[root@redis01 ~]# chown -R mongo.mongo /server/mongo_27017/
4.重新啟動
[root@redis01 ~]# su - mongo
Last login: Wed May 27 09:07:51 CST 2020 on pts/1
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf
3.警告三、四
#你使用的是透明大頁,可能導致mongo延遲和記憶體使用問題。
WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
We suggest setting it to 'never'
WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
We suggest setting it to 'never'
#解決方法:執行 echo never > /sys/kernel/mm/transparent_hugepage/enabled 修復該問題
# 執行 echo never > /sys/kernel/mm/transparent_hugepage/defrag 修復該問題
#配置之後重啟
[root@redis01 ~]# su - mongo
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf --shutdown
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf
#這樣設定是臨時的,我們要把他加到 rc.local,在授個權
4.警告五
#rlimits太低,MongoDB的軟體程序被限制了,MongoDB希望自己是最少rlimits 32767.5
WARNING: soft rlimits too low. rlimits set to 7837 processes, 65535 files. Number of processes should be at least 32767.5 : 0.5 times number of files.
#解決方法:
[root@redis01 ~]# vim /etc/profile
ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -n 65535
ulimit -m unlimited
ulimit -u 65535
[root@redis01 ~]# vim /etc/security/limits.d/20-nproc.conf
* soft nproc 65535
root soft nproc unlimited
[root@redis01 ~]# source /etc/profile
五、基本操作
1.操作說明
CRUD操作是create(建立), read(讀取), update(更新)和delete(刪除) 文件。
MongoDB不支援SQL但是支援自己的豐富的查詢語言。
在MongoDB中,儲存在集合中的每個文件都需要一個唯一的 _id欄位,作為主鍵。如果插入的文件省略了該_id欄位,則MongoDB驅動程式將自動為該欄位生成一個ObjectId_id。也用於通過更新操作插入的文件upsert: true.如果文件包含一個_id欄位,該_id值在集合中必須是唯一的,以避免重複鍵錯誤。
在MongoDB中,插入操作針對單個集合。 MongoDB中的所有寫操作都是在單個文件的級別上進行的
2.基本操作
show databases/show dbs #檢視庫列表
show tables/show collections #檢視所有的集合
use admin #切換庫(沒有的庫也可以進行切換,沒有資料是看不到)
db #檢視當前庫
show users #列印當前資料庫的使用者列表
test:登入時預設存在的庫
admin庫:系統預留庫,MongoDB系統管理庫
local庫:本地預留庫,儲存關鍵日誌
config庫:MongoDB配置資訊庫
3.插入資料
1)單條資料插入
db.test.insert({"name":"lhd","age":18,"sex":"男"})
db.test.insert({"name":"lhd","age":18,"sex":"男","address":"上海浦東新區"})
db.test.insertOne({"name":"lhd","age":18,"sex":"男","address":"上海浦東新區"})
2)多條資料插入
db.inventory.insertMany( [
{ "name": "lhd", "age": 18, "figure": { "h": 182, "w": 200 }, "size": "big" },
{ "name": "qiudao", "age": 88, "figure": { "h": 120, "w": 160 }, "size": "very bittle" },
{ "name": "zengdao", "age": 18, "figure": { "h": 180, "w": 160 }, "size": "nomel" },
]);
4.查詢資料
1)查詢所有資料
> db.test.find()
{ "_id" : ObjectId("5ecdcdac13a4155a65ecb332"), "name" : "lhd", "age" : 18, "sex" : "男" }
{ "_id" : ObjectId("5ecdcdc413a4155a65ecb333"), "name" : "lhd", "age" : 18, "sex" : "男", "address" : "上海浦東新區" }
{ "_id" : ObjectId("5ecdcdd213a4155a65ecb334"), "name" : "lhd", "age" : 18, "sex" : "男" }
{ "_id" : ObjectId("5ecdcdd813a4155a65ecb335"), "name" : "lhd", "age" : 18, "sex" : "男", "address" : "上海浦東新區" }
2)查詢單條資料
> db.test.findOne()
{
"_id" : ObjectId("5ecdcdac13a4155a65ecb332"),
"name" : "lhd",
"age" : 18,
"sex" : "男"
}
3)按條件查詢
#如果查詢條件為數字,不需要加引號
> db.test.findOne({"name" : "lhd"})
{
"_id" : ObjectId("5ecdcdac13a4155a65ecb332"),
"name" : "lhd",
"age" : 18,
"sex" : "男"
}
4)查詢多條件
#並且的多個條件
> db.inventory.find({"figure.h":120,"size":"very bittle"})
> db.inventory.find(
{
"figure.h":120,
"size":"very bittle"
}
)
#表示多條件或者
> db.inventory.find({$or:[{"figure.h":120},{"size":"big"}]})
> db.inventory.find(
{
$or [
{"figure.h":120},
{"size":"big"}
]
}
)
5)條件加範圍的查詢
> db.inventory.find({$or:[{"figure.h":{$lt:130}},{"size":"big"}]})
> db.inventory.find(
{
$or [
{"figure.h":{$lt:130}},
{"size":"big"}
]
}
)
5.修改資料
1)修改單個數據
> db.inventory.updateOne({"name":"qiudao"},{$set:{"figure.h":130}})
> db.inventory.updateOne(
#條件
{"name":"qiudao"},
{
$set:
#修改的值
{"figure.h":130}
}
)
2)修改多條資料
> db.table.updateMany({name:"niulei"},{$set:{age:"18"}})
{ "acknowledged" : true, "matchedCount" : 4, "modifiedCount" : 3 }
6.索引
1)檢視執行計劃
> db.inventory.find().explain()
{ #查詢計劃
"queryPlanner" : {
#計劃版本
"plannerVersion" : 1,
#被查詢的庫和集合
"namespace" : "test2.inventory",
#查詢索引設定
"indexFilterSet" : false,
#查詢條件
"parsedQuery" : {
},
#成功的執行計劃
"winningPlan" : {
#全表掃描
"stage" : "COLLSCAN",
#查詢方向
"direction" : "forward"
},
#拒絕的計劃
"rejectedPlans" : [ ]
},
#伺服器資訊
"serverInfo" : {
"host" : "redis01",
"port" : 27017,
"version" : "3.6.13",
"gitVersion" : "db3c76679b7a3d9b443a0e1b3e45ed02b88c539f"
},
"ok" : 1
}
COLLSCAN 全表掃描
IXSCAN 索引掃描
2)建立索引
> db.inventory.createIndex({"age":1},{background:true})
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
#新增索引
createIndex({索引的名稱:1}) :1表示正序,-1表示倒序
#建立方式
1.前臺方式
預設情況下,當為一個集合建立索引時,這個操作將阻塞其他的所有操作。即該集合上的無法正常讀寫,直到索引建立完畢
任意基於所有資料庫申請讀或寫鎖都將等待直到前臺完成索引建立操作
2.後臺方式
將索引建立置於到後臺,適用於那些需要長時間建立索引的情形
這樣子在建立索引期間,MongoDB依舊可以正常的為提供讀寫操作服務
等同於關係型資料庫在建立索引的時候指定online,而MongoDB則是指定background
其目的都是相同的,即在索引建立期間,儘可能的以一種佔用較少的資源佔用方式來實現,同時又可以提供讀寫服務
後臺建立方式的代價:索引建立時間變長
#規範
1.如果要查詢的內容都是最近的,那建立索引就用倒序,如果要通盤查詢那就用正序。
2.比如說一個數據集合查詢佔的比較多就用索引,如果查詢少而是插入資料比較多就不用建立索引。因為:當沒有索引的時候,插入資料的時候MongoDB會在記憶體中分配出一塊空間,用來存放資料。當有索引的時候在插入資料之後還會給自動新增一個索引,浪費了時間。
3.不是所有資料都要建立索引,要在恰當並且需要的地方建立才是最好的。
4.大數量的排序工作時可以考慮建立索引。
3)檢視索引
> db.inventory.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test2.test2"
},
{
"v" : 2,
"key" : {
"age" : 1
},
"name" : "name_1",
"ns" : "test2.test2",
"background" : true
}
]
4)再次檢視執行計劃
> db.inventory.find({"age":{$lt:40}}).explain()
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
#走索引了
"stage" : "IXSCAN",
6.刪除
1)刪除單條資料
> db.inventory.deleteOne({"name":"lhd"})
{ "acknowledged" : true, "deletedCount" : 1 }
2)刪除多個數據
> db.inventory.deleteMany({"name":"lhd"})
3)刪除索引
> db.test.dropIndex({ age: 1 })
{
"ok" : 0,
"errmsg" : "ns not found",
"code" : 26,
"codeName" : "NamespaceNotFound"
}
4)刪除集合
#先確認自己在哪個庫
> db
test2
#確認集合
> show tables;
inventory
test
#刪除集合
> db.inventory.drop()
true
5)刪除庫
#先確認自己在哪個庫
> db
test2
#刪除庫
> db.dropDatabase()
六、mongo工具
mongo #登入命令
mongodump #備份匯出,全備(資料時壓縮過的)
mongorestore #恢復資料
mongostat #檢視執行狀態的
mongod #啟動命令
mongoexport #備份,匯出json格式
mongoimport #恢復資料
mongos #叢集分片命令
mongotop #檢視執行狀態
1.mongostat命令
#不加任何引數時,每秒訪問一次
[mongo@redis01 ~]$ mongostat
insert query update delete getmore command dirty used flushes vsize res qrw arw net_in net_out conn time
*0 *0 *0 *0 0 2|0 0.0% 0.0% 0 972M 56.0M 0|0 1|0 158b 60.9k 1 May 27 11:23:08.248
insert #每秒插入資料的數量
query #每秒查詢操作的數量
update #每秒更新資料的數量
delete #沒面刪除操作的數量
getmore #每秒查詢遊標時的運算元
command #每秒執行的命令數
dirty #髒資料佔快取的多少
used #使用中的快取
flushes
#在 wiredtiger引擎,表示輪詢間隔
#在MMapv1引擎,表示每秒寫入磁碟次數
vsize #虛擬記憶體使用量
res #實體記憶體使用量
qrw #客戶端等待讀資料的佇列長度
arw #客戶端等待寫入資料的佇列長度
net_in #網路進流量
net_out #網路出流量
conn #連線總數
time #時間
#一般該命令搭配 mongotop 命令使用,可以顯示每個集合的響應速度
七、使用者授權認證
1.授權命令
使用者管理介面
要新增使用者, MongoDB提供了該db.createUser()方法。新增使用者時,您可以為使用者分配色以授予許可權。
注意:
在資料庫中建立的第一個使用者應該是具有管理其他使用者的許可權的使用者管理員。
您還可以更新現有使用者,例如更改密碼並授予或撤銷角色。
db.auth() 將使用者驗證到資料庫。
db.changeUserPassword() 更改現有使用者的密碼。
db.createUser() 建立一個新使用者。
db.dropUser() 刪除單個使用者。
db.dropAllUsers() 刪除與資料庫關聯的所有使用者。
db.getUser() 返回有關指定使用者的資訊。
db.getUsers() 返回有關與資料庫關聯的所有使用者的資訊。
db.grantRolesToUser() 授予使用者角色及其特權。
db.removeUser() 已過時。從資料庫中刪除使用者。
db.revokeRolesFromUser() 從使用者中刪除角色。
db.updateUser() 更新使用者資料。
2.建立使用者和角色
[mongo@db01 ~]$ mongo
> use admin
> db.createUser({user: "admin",pwd: "123456",roles:[ { role: "root", db:"admin"}]})
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
3.檢視使用者
> db.getUsers()
[
{
"_id" : "test.admin",
"userId" : UUID("b840b96c-3442-492e-a45f-6ca7dff907fd"),
"user" : "admin",
"db" : "test",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
]
4.配置開啟認證
[root@redis01 ~]# vim /server/mongo_27017/conf/mongodb.conf
security:
authorization: enabled
#重啟
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf --shutdown
[mongo@redis01 ~]$ mongod -f /server/mongo_27017/conf/mongodb.conf
5.配置認證以後查操作不了
> show databases;
2020-05-27T11:41:06.186+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "there are no users authenticated",
"code" : 13,
"codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
shellHelper.show@src/mongo/shell/utils.js:860:19
shellHelper@src/mongo/shell/utils.js:750:15
@(shellhelp2):1:1
6.使用賬號密碼連線
[mongo@redis01 ~]$ mongo -uadmin -p --authenticationDatabase admin
MongoDB shell version v3.6.13
Enter password:
> show databases;
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
test2 0.000GB
7.建立普通使用者
> use test
> db.createUser(
{
user: "test",
pwd: "123456",
roles: [ { role: "readWrite", db: "write" },
{ role: "read", db: "read" } ]
}
)
8.建立測試資料
use write
db.write.insert({"name":"linhaoda","age":17,"ad":"上海浦東新區"})
db.write.insert({"name":"linhaoda","age":17,"ad":"上海浦東新區"})
db.write.insert({"name":"haoda","age":18,"ad":"上海浦東新區"})
db.write.insert({"name":"linda","age":18,"ad":"上海浦東新區"})
db.write.insert({"name":"linhao","age":18,"ad":"上海浦東新區","sex":"boy"})
use read
db.read.insert({"name":"linhaoda","age":17,"ad":"上海浦東新區"})
db.read.insert({"name":"linhaoda","age":17,"ad":"上海浦東新區"})
db.read.insert({"name":"haoda","age":18,"ad":"上海浦東新區"})
db.read.insert({"name":"linda","age":18,"ad":"上海浦東新區"})
db.read.insert({"name":"linhao","age":18,"ad":"上海浦東新區","sex":"boy"})
9.驗證
mongo -utest -p --authenticationDatabase test
use write
db.write.find()
db.write.insert({"name":"linhaoda","age":17,"ad":"上海浦東新區"})
use read
db.read.find()
db.read.insert({"name":"linhaoda","age":17,"ad":"上海浦東新區"})
10.修改使用者密碼
#修改使用者資訊
db.updateUser("test",{pwd:"123"})
#修改密碼
db.changeUserPassword("admin","123")