簡介:html
MongoDB提供了多樣性的索引支持,索引信息被保存在system.indexes中,MongoDB中的_id字段在建立的時候,默認已經創建了索引,這個索引比較特殊,而且不可刪除,不過Capped Collections例外。git
注意事項:在3.0.0版本前建立索引的方法爲db.collection.ensureIndex(),以後的版本使用db.collection.createIndex(),ensureIndex()還能用,但只是createIndex()的別名。mongodb
創建索引的函數:ensureIndex()數據庫
例子:在name上創建索引 1(升序), -1(降序) ,eg:>db.c1.ensureIndex({name:1});安全
當系統已經有大量數據時,建立索引很是耗時,須要在後臺執行,只需指定「backgroud:true」便可。性能優化
>db.c1.ensureIndex({age:1},{background:true});bash
插入測試數據:>for(i=1;i<=10;i++) {
... db.c1.insert({name:"user"+i,age:i});
... }網絡
查找name爲"user5"的記錄的查詢過程:>db.c1.find({name:"user5"}).explain();app
給name增長一個索引:> db.c1.ensureIndex({name:1});ide
createIndex()方法中也能夠設置使用多個字段建立索引(關係型數據庫中稱爲複合索引) :> db.c1.createIndex({name:1,age:-1});
查看如今全部的索引:> db.c1.getIndexKeys();
結果:[ { "_id" : 1 }, { "name" : 1 } ]
查看全部的索引:> db.c1.getIndexes();
> db.c1.getIndexes(); [ { "v" : 2, "key" : { "_id" : 1 #索引所在的列 }, "name" : "_id_", #索引的名稱 "ns" : "test.c1" }, { "v" : 2, "key" : { "name" : 1 #索引所在的列 }, "name" : "name_1", #索引的名稱 "ns" : "test.c1" } ]
只須要在ensureIndex命令中指定「unique:true」便可建立惟一索引。
建立惟一索引:> db.c1.ensureIndex({age:1},{unique:1});
查看索引:>db.c1.getIndexKeys();
結果:[ { "_id" : 1 }, { "name" : 1 }, { "age" : 1 } ]
查看索引:>> db.c1.getIndexes();
此時發現:
#由於有age=10的記錄了,因此再插入age爲10的記錄,報惟一索引錯誤!! > db.c1.insert({name:"user11",age:10}); WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error collection: test.c1 index: age_1 dup key: { : 10.0 }" } }) >
查看索引用的命令:getIndexes();
#其中_id是建立集合的時候自動建立的索引,此索引是不可以刪除。 > db.c1.getIndexes(); [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.c1" }, { "v" : 2, "key" : { "name" : 1 }, "name" : "name_1", "ns" : "test.c1" }, { "v" : 2, "unique" : true, "key" : { "age" : 1 }, "name" : "age_1", "ns" : "test.c1" } ]
刪除索引的命令:dropIndexes();
//刪除索引 "name" : "idx_score",
db.hotspot_video.dropIndex("idx_score");
#刪除age索引 > db.c1.dropIndex({age:1}); { "nIndexesWas" : 3, "ok" : 1 } > db.c1.getIndexKeys(); [ { "_id" : 1 }, { "name" : 1 } ] #刪除全部的索引 > db.c1.dropIndexes(); { "nIndexesWas" : 2, "msg" : "non-_id indexes dropped for collection", "ok" : 1 } > db.c1.getIndexes(); [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.c1" } ] #如上,能夠看到_id的索引是不能刪除的!
簡介:
MongoDB提供了一個explain命令讓咱們獲知系統如何查詢請求。利用explain命令咱們能夠很好的觀察系統如何使用索引來加快檢索,同時能夠針對性優化索引。
MongoDB3.0以上,explain()有三個可選的模式有」queryPlanner」, 「executionStats」, 和 「allPlansExecution」.傳入true表明allPlansExecution mode, 傳入false或者默認爲queryPlanner mode.
#查看執行過程! > db.c1.find({name:"user5"}).explain("executionStats"); { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.c1", "indexFilterSet" : false, "parsedQuery" : { "name" : { "$eq" : "user5" } }, "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "name" : { "$eq" : "user5" } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "executionStats" : { "executionSuccess" : true, ###執行是否成功 "nReturned" : 1, ### 返回的文檔數 "executionTimeMillis" : 0, ###執行的時間 "totalKeysExamined" : 0, ###索引掃描條數 "totalDocsExamined" : 10, ###文檔掃描條數 "executionStages" : { "stage" : "COLLSCAN", ### 表明CollectionScan-集合掃描! "filter" : { "name" : { "$eq" : "user5" } }, "nReturned" : 1, ### 表明返回的個數! "executionTimeMillisEstimate" : 0, "works" : 12, "advanced" : 1, ###過程當中應該返回的文檔數量 "needTime" : 10, "needYield" : 0, ###過程當中被打斷的次數 "saveState" : 0, "restoreState" : 0, "isEOF" : 1, ###指定查詢是否已經結束 "invalidates" : 0, "direction" : "forward", ###查詢的方式 "docsExamined" : 10 ###表明掃描行數爲10 } }, "serverInfo" : { "host" : "localhost", "port" : 27017, "version" : "3.6.4", "gitVersion" : "d0181a711f7e7f39e60b5aeb1dc7097bf6ae5856" }, "ok" : 1 }
創建索引後的查找:
###爲name創建索引 > db.c1.createIndex({name:1}); { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } > db.c1.find({name:"user5"}).explain("executionStats"); { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.c1", "indexFilterSet" : false, "parsedQuery" : { "name" : { "$eq" : "user5" } }, "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "name" : 1 }, "indexName" : "name_1", "isMultiKey" : false, "multiKeyPaths" : { "name" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "name" : [ "[\"user5\", \"user5\"]" ] } } }, "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, "invalidates" : 0, "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, "invalidates" : 0, "keyPattern" : { "name" : 1 }, "indexName" : "name_1", "isMultiKey" : false, "multiKeyPaths" : { "name" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { ###使用到的索引 "name" : [ "[\"user5\", \"user5\"]" ] }, "keysExamined" : 1, "seeks" : 1, "dupsTested" : 0, "dupsDropped" : 0, "seenInvalidated" : 0 } } }, "serverInfo" : { "host" : "localhost", "port" : 27017, "version" : "3.6.4", "gitVersion" : "d0181a711f7e7f39e60b5aeb1dc7097bf6ae5856" }, "ok" : 1 } >
Stage狀態分析
stage | 描述 |
---|---|
COLLSCAN | 全表掃描 |
IXSCAN | 掃描索引 |
FETCH | 根據索引去檢索指定document |
SHARD_MERGE | 將各個分片返回數據進行merge |
SORT | 代表在內存中進行了排序 |
LIMIT | 使用limit限制返回數 |
SKIP | 使用skip進行跳過 |
IDHACK | 針對_id進行查詢 |
SHARDING_FILTER | 經過mongos對分片數據進行查詢 |
COUNT | 利用db.coll.explain().count()之類進行count運算 |
COUNTSCAN | count不使用Index進行count時的stage返回 |
COUNT_SCAN | count使用了Index進行count時的stage返回 |
SUBPLA | 未使用到索引的$or查詢的stage返回 |
TEXT | 使用全文索引進行查詢時候的stage返回 |
PROJECTION | 限定返回字段時候stage的返回 |
MongoDB Database Profiler 是一種慢查詢日誌功能,能夠做爲咱們優化數據庫的依據。
開啓Profiling功能:
《1.》方法一:啓動時,加上--profle=級別便可。
《2.》方法二:在客戶端調用db.setProfilingLevel(級別)命令來實時配置。
Profiler信息保存在system.profile中。咱們能夠經過db.getProfilingLevel()命令來獲取當前的Profile級別。
profile的級別能夠取0,1,2三個值,他們的表示是:
0-不開啓【默認值】
1-記錄慢命令(默認爲>100ms)
2-記錄全部命令
> db.getProfilingLevel(); 0 > db.setProfilingLevel(1); { "was" : 0, "slowms" : 100, "sampleRate" : 1, "ok" : 1 } > db.getProfilingLevel(); 1
Profile在級別爲1時會記錄慢命令,上面的默認值爲100ms,有默認就有設置,其設置方法和級別的方法以下:
《1.》方法一:經過添加--slowms啓動參數設置。
《2.》方法二:db.setProfilingLevel(參數1,參數2)時,加上第二個參數!(貌似此方法很差用!!)
優化方案1:建立索引
在查詢條件的字段上,或者排序條件的字段上建立索引,能夠顯著提升執行效率。
db.c1.ensureIndex({name:1});
優化方案2:限定返回結果條數
使用limit()限定返回結果集的大小,能夠減小database server的資源消耗,能夠減小網絡傳輸的數據量。
db.c1.find().sort({age:-1}).limit(3);
優化方案3:查詢使用到的字段,不查詢全部的字段
db.c1.find({},{name:1,age:1}).sort({age:1}).skip(3).limit(2);
優化方案4:採用cappedcollection
capped Collections比普通的Collections的讀寫效率高
優化方案5:採用Profiling
Profling功能確定會影響效率的,可是不太嚴重,緣由是它使用的是system.profile來記錄,system.profile是一個capped collection。這種collection在操做上有一些限制和特色,可是效率高!
經過對數據庫的性能監控,可以更好的瞭解數據庫的工做狀態,從而進行優化。
MongoDB 3.4 引入 mongoreplay 工具,可用於監控並記錄 mongod 上執行的命令並 replay 到另外一個 mongod 實例上,該工具可用於代替 mongosniff。
mongosniff【此工具能夠從底層監控到底有那些命令發送個體MongoDB去執行。
它是實時動態監視的,須要打開另外一個客戶端進行命令操做。能夠將這些數據輸出到一個日誌文件中,那麼久能夠保留下全部數據庫操做的歷史記錄,對於後期的性能分析和安全審計等工做將是一個巨大的貢獻。】
詳細參考:https://bbs.huaweicloud.com/blogs/ac80aa383b9d11e89fc57ca23e93a89f
此工具能夠快速的查看某組運行中的MongoDB實例的統計信息,也須要在打開一個客戶端進行命令操做:
它會間隔固定時間獲取mongodb的當前運行狀態,並輸出。若是你發現數據庫忽然變慢或有其餘問題的話,你第一手的操做就是考慮採用mongostat來查看mongo的狀態。
[root@localhost bin]# /usr/local/mongodb/bin/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.1% 0 1020M 86.0M 0|0 1|0 158b 59.1k 2 May 27 03:22:59.566 *0 *0 *0 *0 0 1|0 0.0% 0.1% 0 1020M 86.0M 0|0 1|0 157b 58.8k 2 May 27 03:23:00.566 *0 *0 *0 *0 0 1|0 0.0% 0.1% 0 1020M 86.0M 0|0 1|0 157b 58.7k 2 May 27 03:23:01.569 *0 *0 *0 *0 0 1|0 0.0% 0.1% 0 1020M 86.0M 0|0 1|0 157b 58.8k 2 May 27 03:23:02.570
mongotop也是mongodb下的一個內置工具,mongotop提供了一個方法,用來跟蹤一個MongoDB的實例,查看哪些大量的時間花費在讀取和寫入數據。 mongotop提供每一個集合的水平的統計數據。默認狀況下,mongotop返回值的每一秒。
若是每10s返回一次能夠用> # /usr/local/mongodb/bin/mongotop 10