MongoDB 是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù)。由 C++ 語言編寫。旨在為 WEB 應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。
MongoDB 是一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫(kù)當(dāng)中功能最豐富,最像關(guān)系數(shù)據(jù)庫(kù)的。
一、索引
MongoDB 提供了多樣性的索引支持,索引信息被保存在system.indexes 中,且默認(rèn)總是為_id創(chuàng)建索引,它的索引使用基本和MySQL 等關(guān)系型數(shù)據(jù)庫(kù)一樣。其實(shí)可以這樣說說,索引是凌駕于數(shù)據(jù)存儲(chǔ)系統(tǒng)之上的另一層系統(tǒng),所以各種結(jié)構(gòu)迥異的存儲(chǔ)都有相同或相似的索引實(shí)現(xiàn)及使用接口并不足為 奇。
1.基礎(chǔ)索引
在字段age 上創(chuàng)建索引,1(升序);-1(降序):
db.users.ensureIndex({age:1})
_id 是創(chuàng)建表的時(shí)候自動(dòng)創(chuàng)建的索引,此索引是不能夠刪除的。當(dāng)系統(tǒng)已有大量數(shù)據(jù)時(shí),創(chuàng)建索引就是個(gè)非常耗時(shí)的活,我們可以在后臺(tái)執(zhí)行,只需指定“backgroud:true”即可。
db.t3.ensureIndex({age:1} , {backgroud:true})
2.文檔索引
索引可以任何類型的字段,甚至文檔:
db.factories.insert( { name: "wwl", addr: { city: "Beijing", state: "BJ" } } );
//在addr 列上創(chuàng)建索引
db.factories.ensureIndex( { addr : 1 } );
//下面這個(gè)查詢將會(huì)用到我們剛剛建立的索引
db.factories.find( { addr: { city: "Beijing", state: "BJ" } } );
//但是下面這個(gè)查詢將不會(huì)用到索引,因?yàn)椴樵兊捻樞蚋饕⒌捻樞虿灰粯?
db.factories.find( { addr: { state: "BJ" , city: "Beijing"} } );
3. 組合索引
跟其它數(shù)據(jù)庫(kù)產(chǎn)品一樣,MongoDB 也是有組合索引的,下面我們將在addr.city 和addr.state上建立組合索引。當(dāng)創(chuàng)建組合索引時(shí),字段后面的1 表示升序,-1 表示降序,是用1 還是用-1 主要是跟排序的時(shí)候或指定范圍內(nèi)查詢 的時(shí)候有關(guān)的。
db.factories.ensureIndex( { "addr.city" : 1, "addr.state" : 1 } );
// 下面的查詢都用到了這個(gè)索引
db.factories.find( { "addr.city" : "Beijing", "addr.state" : "BJ" } );
db.factories.find( { "addr.city" : "Beijing" } );
db.factories.find().sort( { "addr.city" : 1, "addr.state" : 1 } );
db.factories.find().sort( { "addr.city" : 1 } )
4. 唯一索引
只需在ensureIndex 命令中指定”unique:true”即可創(chuàng)建唯一索引。例如,往表t4 中插入2 條記錄:
db.t4.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
5.強(qiáng)制使用索引
hint 命令可以強(qiáng)制使用某個(gè)索引。
db.t5.find({age:{$lt:30}}).hint({name:1, age:1}).explain()
6.刪除索引
//刪除t3 表中的所有索引
db.t3.dropIndexes()
//刪除t4 表中的firstname 索引
db.t4.dropIndex({firstname: 1})
二、explain執(zhí)行計(jì)劃
MongoDB 提供了一個(gè) explain 命令讓我們獲知系統(tǒng)如何處理查詢請(qǐng)求。利用 explain 命令,我們可以很好地觀察系統(tǒng)如何使用索引來加快檢索,同時(shí)可以針對(duì)性優(yōu)化索引。
db.t5.ensureIndex({name:1})
db.t5.ensureIndex({age:1})
db.t5.find({age:{$gt:45}}, {name:1}).explain()
{
"cursor" : "BtreeCursor age_1",
"nscanned" : 0,
"nscannedObjects" : 0,
"n" : 0,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
"age" : [
[45,1.7976931348623157e+308]
]
}
}
字段說明:
•cursor: 返回游標(biāo)類型(BasicCursor 或 BtreeCursor)
•nscanned: 被掃描的文檔數(shù)量
•n: 返回的文檔數(shù)量
•millis: 耗時(shí)(毫秒)
•indexBounds: 所使用的索引
三、優(yōu)化器profile
在MySQL 中,慢查詢?nèi)罩臼墙?jīng)常作為我們優(yōu)化數(shù)據(jù)庫(kù)的依據(jù),那在MongoDB 中是否有類似的功能呢?答案是肯定的,那就是MongoDB Database Profiler。
1.開啟profiling功能
有兩種方式可以控制 Profiling 的開關(guān)和級(jí)別,第一種是直接在啟動(dòng)參數(shù)里直接進(jìn)行設(shè)置。啟動(dòng)MongoDB 時(shí)加上–profile=級(jí)別 即可。也可以在客戶端調(diào)用db.setProfilingLevel(級(jí)別) 命令來實(shí)時(shí)配置,Profiler 信息保存在system.profile 中。我們可以通過db.getProfilingLevel()命令來獲取當(dāng)前的Profile 級(jí)別,類似如下操作:
上面profile 的級(jí)別可以取0,1,2 三個(gè)值,他們表示的意義如下:
1.0 – 不開啟
2.1 – 記錄慢命令 (默認(rèn)為>100ms)
3.2 – 記錄所有命令
Profile 記錄在級(jí)別1 時(shí)會(huì)記錄慢命令,那么這個(gè)慢的定義是什么?上面我們說到其默認(rèn)為100ms,當(dāng)然有默認(rèn)就有設(shè)置,其設(shè)置方法和級(jí)別一樣有兩種,一種是通過添加 –slowms 啟動(dòng)參數(shù)配置。第二種是調(diào)用db.setProfilingLevel 時(shí)加上第二個(gè)參數(shù):
db.setProfilingLevel( level , slowms )
db.setProfilingLevel( 1 , 10 );
2.查詢 Profiling 記錄
與MySQL 的慢查詢?nèi)罩静煌?,MongoDB Profile 記錄是直接存在系統(tǒng)db 里的,記錄位置system.profile ,所以,我們只要查詢這個(gè)Collection 的記錄就可以獲取到我們的 Profile 記錄了。列出執(zhí)行時(shí)間長(zhǎng)于某一限度(5ms)的 Profile 記錄:
db.system.profile.find( { millis : { $gt : 5 } } )
MongoDB Shell 還提供了一個(gè)比較簡(jiǎn)潔的命令show profile,可列出最近5 條執(zhí)行時(shí)間超過1ms 的 Profile 記錄。
四、常用性能優(yōu)化方案
1.創(chuàng)建索引
2.限定返回結(jié)果數(shù)
3.只查詢使用到的字段
4.采用capped collection
5.采用Server Side Code Execution
6.使用Hint,強(qiáng)制使用索引
7.采用Profiling
五、性能監(jiān)控工具
1. mongosniff
此工具可以從底層監(jiān)控到底有哪些命令發(fā)送給了MongoDB 去執(zhí)行,從中就可以進(jìn)行分析:以root 身份執(zhí)行:
$./mongosniff --source NET lo
然后其會(huì)監(jiān)控位到本地以localhost 監(jiān)聽默認(rèn)27017 端口的MongoDB 的所有包請(qǐng)求。
2.Mongostat
此工具可以快速的查看某組運(yùn)行中的MongoDB 實(shí)例的統(tǒng)計(jì)信息 字段說明:
•insert: 每秒插入量
•query: 每秒查詢量
•update: 每秒更新量
•delete: 每秒刪除量
•locked: 鎖定量
•qr | qw: 客戶端查詢排隊(duì)長(zhǎng)度(讀|寫)
•ar | aw: 活躍客戶端量(讀|寫)
•conn: 連接數(shù)
•time: 當(dāng)前時(shí)間
它每秒鐘刷新一次狀態(tài)值,提供良好的可讀性,通過這些參數(shù)可以觀察到一個(gè)整體的性能情況。
3. db.serverStatus
這個(gè)命令是最常用也是最基礎(chǔ)的查看實(shí)例運(yùn)行狀態(tài)的命令之一。
4.db.stats
下面給大家介紹下mongodb的監(jiān)控
mongodb可以通過profile來監(jiān)控?cái)?shù)據(jù),進(jìn)行優(yōu)化。
查看當(dāng)前是否開啟profile功能用命令
db.getProfilingLevel() 返回level等級(jí),值為0|1|2,分別代表意思:0代表關(guān)閉,1代表記錄慢命令,2代表全部開始profile功能為
db.setProfilingLevel(level); #level等級(jí),值同上level為1的時(shí)候,慢命令默認(rèn)值為100ms,更改為db.setProfilingLevel(level,slowms)如db.setProfilingLevel(1,50)這樣就更改為50毫秒通過db.system.profile.find() 查看當(dāng)前的監(jiān)控日志。
如:
> db.system.profile.find({millis:{$gt:500}})
{ "ts" : ISODate("2011-07-23T02:50:13.941Z"), "info" : "query order.order reslen:11022 nscanned:672230 \nquery: { status: 1.0 } nreturned:101 bytes:11006 640ms", "millis" : 640 }
{ "ts" : ISODate("2011-07-23T02:51:00.096Z"), "info" : "query order.order reslen:11146 nscanned:672302 \nquery: { status: 1.0, user.uid: { $gt: 1663199.0 } } nreturned:101 bytes:11130 647ms", "millis" : 647 }
這里值的含義是
ts:命令執(zhí)行時(shí)間
info:命令的內(nèi)容
query:代表查詢
order.order: 代表查詢的庫(kù)與集合
reslen:返回的結(jié)果集大小,byte數(shù)
nscanned:掃描記錄數(shù)量
nquery:后面是查詢條件
nreturned:返回記錄數(shù)及用時(shí)
millis:所花時(shí)間
如果發(fā)現(xiàn)時(shí)間比較長(zhǎng),那么就需要作優(yōu)化。
比如nscanned數(shù)很大,或者接近記錄總數(shù),那么可能沒有用到索引查詢。
reslen很大,有可能返回沒必要的字段。
nreturned很大,那么有可能查詢的時(shí)候沒有加限制。
mongo可以通過db.serverStatus()查看mongod的運(yùn)行狀態(tài)
> db.serverStatus()
{
"host" : "baobao-laptop",#主機(jī)名
"version" : "1.8.2",#版本號(hào)
"process" : "mongod",#進(jìn)程名
"uptime" : 15549,#運(yùn)行時(shí)間
"uptimeEstimate" : 15351,
"localTime" : ISODate("2011-07-23T06:07:31.220Z"),當(dāng)前時(shí)間
"globalLock" : {
"totalTime" : 15548525410,#總運(yùn)行時(shí)間(ns)
"lockTime" : 89206633, #總的鎖時(shí)間(ns)
"ratio" : 0.005737305027178137,#鎖比值
"currentQueue" : {
"total" : 0,#當(dāng)前需要執(zhí)行的隊(duì)列
"readers" : 0,#讀隊(duì)列
"writers" : 0#寫隊(duì)列
},
"activeClients" : {
"total" : 0,#當(dāng)前客戶端執(zhí)行的鏈接數(shù)
"readers" : 0,#讀鏈接數(shù)
"writers" : 0#寫鏈接數(shù)
}
},
"mem" : {#內(nèi)存情況
"bits" : 32,#32位系統(tǒng)
"resident" : 337,#占有物理內(nèi)存數(shù)
"virtual" : 599,#占有虛擬內(nèi)存
"supported" : true,#是否支持?jǐn)U展內(nèi)存
"mapped" : 512
},
"connections" : {
"current" : 2,#當(dāng)前鏈接數(shù)
"available" : 817#可用鏈接數(shù)
},
"extra_info" : {
"note" : "fields vary by platform",
"heap_usage_bytes" : 159008,#堆使用情況字節(jié)
"page_faults" : 907 #頁面故作
},
"indexCounters" : {
"btree" : {
"accesses" : 59963, #索引被訪問數(shù)
"hits" : 59963, #所以命中數(shù)
"misses" : 0,#索引偏差數(shù)
"resets" : 0,#復(fù)位數(shù)
"missRatio" : 0#未命中率
}
},
"backgroundFlushing" : {
"flushes" : 259, #刷新次數(shù)
"total_ms" : 3395, #刷新總花費(fèi)時(shí)長(zhǎng)
"average_ms" : 13.108108108108109, #平均時(shí)長(zhǎng)
"last_ms" : 1, #最后一次時(shí)長(zhǎng)
"last_finished" : ISODate("2011-07-23T06:07:22.725Z")#最后刷新時(shí)間
},
"cursors" : {
"totalOpen" : 0,#打開游標(biāo)數(shù)
"clientCursors_size" : 0,#客戶端游標(biāo)大小
"timedOut" : 16#超時(shí)時(shí)間
},
"network" : {
"bytesIn" : 285676177,#輸入數(shù)據(jù)(byte)
"bytesOut" : 286564,#輸出數(shù)據(jù)(byte)
"numRequests" : 2012348#請(qǐng)求數(shù)
},
"opcounters" : {
"insert" : 2010000, #插入操作數(shù)
"query" : 51,#查詢操作數(shù)
"update" : 5,#更新操作數(shù)
"delete" : 0,#刪除操作數(shù)
"getmore" : 0,#獲取更多的操作數(shù)
"command" : 148#其他命令操作數(shù)
},
"asserts" : {#各個(gè)斷言的數(shù)量
"regular" : 0,
"warning" : 0,
"msg" : 0,
"user" : 2131,
"rollovers" : 0
},
"writeBacksQueued" : false,
"ok" : 1
}
db.stats()查看某一個(gè)庫(kù)的原先狀況
> db.stats()
{
"db" : "order",#庫(kù)名
"collections" : 4,#集合數(shù)
"objects" : 2011622,#記錄數(shù)
"avgObjSize" : 111.92214441878245,#每條記錄的平均值
"dataSize" : 225145048,#記錄的總大小
"storageSize" : 307323392,#預(yù)分配的存儲(chǔ)空間
"numExtents" : 21,#事件數(shù)
"indexes" : 1,#索引數(shù)
"indexSize" : 74187744,#所以大小
"fileSize" : 1056702464,#文件大小
"ok" : 1
}
查看集合記錄用
> db.order.stats()
{
"ns" : "order.order",#命名空間
"count" : 2010000,#記錄數(shù)
"size" : 225039600,#大小
"avgObjSize" : 111.96,
"storageSize" : 307186944,
"numExtents" : 18,
"nindexes" : 1,
"lastExtentSize" : 56089856,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 74187744,
"indexSizes" : {
"_id_" : 74187744#索引為_id_的索引大小
},
"ok" : 1
}
mongostat命令查看運(yùn)行中的實(shí)時(shí)統(tǒng)計(jì),表示每秒實(shí)時(shí)執(zhí)行的次數(shù)
mongodb還提供了一個(gè)機(jī)遇http的監(jiān)控頁面,可以訪問http://ip:28017來查看,這個(gè)頁面基本上是對(duì)上面的這些命令做了一下綜合,所以這里不細(xì)述了。
您可能感興趣的文章:- mongodb監(jiān)控工具mongostat的使用及命令詳解
- Zabbix3.4監(jiān)控mongodb數(shù)據(jù)庫(kù)狀態(tài)的方法
- python監(jiān)控linux內(nèi)存并寫入mongodb(推薦)
- 利用MongoDB中oplog機(jī)制實(shí)現(xiàn)準(zhǔn)實(shí)時(shí)數(shù)據(jù)的操作監(jiān)控
- 使用zabbix監(jiān)控mongodb的方法
- MongoDB運(yùn)行狀態(tài)監(jiān)控、性能分析工具mongostat詳解
- MongoDB 監(jiān)控工具mongostat和mongotop的使用