MongoDB數(shù)據(jù)庫中索引和explain的使用教程
前言
本文主要給大家介紹了關(guān)于MongoDB中索引和explain使用的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹:
mongodb 索引使用
作用
- 索引通常能夠極大的提高查詢。
- 索引是一種數(shù)據(jù)結(jié)構(gòu),他搜集一個(gè)集合中文檔特定字段的值。
- B-Tree索引來實(shí)現(xiàn)。
創(chuàng)建索引
db.collection.createIndex(keys, options)
keys
- keys由文檔字段和索引類型組成。如{"name":1}
- key 表示字段 value 1,-1 1表示升序,-1降序
options
options 創(chuàng)建索引的選項(xiàng)。
參數(shù) | 類型 | 描述 |
---|---|---|
background | boolean | 創(chuàng)建索引在后臺(tái)運(yùn)行,不會(huì)阻止其他對(duì)數(shù)據(jù)庫操作 |
unique | boolean | 創(chuàng)建唯一索引,文檔的值不會(huì)重復(fù) |
name | string | 索引名稱,默認(rèn)是:字段名_排序類型 開始排序 |
sparse | boolean | 過濾掉null,不存在的字段 |
查看索引
db.collection.getIndexes()
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.userdatas" }, { "v" : 1, "key" : { "name" : 1 //索引字段 }, "name" : "name_1", //索引名稱 "ns" : "leyue.userdatas" }
刪除索引
db.collection.dropIndex(index)
刪除指定的索引。
db.collection.dropIndexes()
刪除除了_id 以外的所有索引。
- index 是字符串 表示按照索引名稱 name 刪除字段。
- index 是{字段名稱:1} 表示按照key 刪除索引。
創(chuàng)建/查看/刪除 示例
查看數(shù)據(jù)
db.userdatas.find() { "_id" : ObjectId("597f357a09c84cf58880e412"), "name" : "u3", "age" : 32 } { "_id" : ObjectId("597f357a09c84cf58880e411"), "name" : "u4", "age" : 30, "score" : [ 7, 4, 2, 0 ] } { "_id" : ObjectId("597fcc0f411f2b2fd30d0b3f"), "age" : 20, "score" : [ 7, 4, 2, 0, 10, 9, 8, 7 ], "name" : "lihao" } { "_id" : ObjectId("597f357a09c84cf58880e413"), "name" : "u2", "age" : 33, "wendang" : { "yw" : 80, "xw" : 90 } } { "_id" : ObjectId("5983f5c88eec53fbcd56a7ca"), "date" : ISODate("2017-08-04T04:19:20.693Z") } { "_id" : ObjectId("597f357a09c84cf58880e40e"), "name" : "u1", "age" : 26, "address" : "中國碭山" } { "_id" : ObjectId("597f357a09c84cf58880e40f"), "name" : "u1", "age" : 37, "score" : [ 10, 203, 12, 43, 56, 22 ] } { "_id" : ObjectId("597f357a09c84cf58880e410"), "name" : "u5", "age" : 78, "address" : "china beijing chaoyang" }
給字段name 創(chuàng)建索引
// 創(chuàng)建索引 db.userdatas.createIndex({"name":1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } // 查看索引 db.userdatas.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.userdatas" }, { "v" : 1, "key" : { "name" : 1 }, "name" : "name_1", "ns" : "leyue.userdatas" } ]
給字段name 創(chuàng)建索引并命名為myindex
db.userdatas.createIndex({"name":1}) db.userdatas.createIndex({"name":1},{"name":"myindex"}) db.userdatas.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.userdatas" }, { "v" : 1, "key" : { "name" : 1 }, "name" : "myindex", "ns" : "leyue.userdatas" } ]
給字段name 創(chuàng)建索引 創(chuàng)建的過程在后臺(tái)執(zhí)行
當(dāng)mongodb 集合里面的數(shù)據(jù)過大時(shí) 創(chuàng)建索引很耗時(shí),可以在放在后臺(tái)運(yùn)行。
db.userdatas.dropIndex("myindex") db.userdatas.createIndex({"name":1},{"name":"myindex","background":true})
給age 字段創(chuàng)建唯一索引
db.userdatas.createIndex({"age":-1},{"name":"ageIndex","unique":true,"sparse":true}) db.userdatas.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.userdatas" }, { "v" : 1, "key" : { "name" : 1 }, "name" : "myindex", "ns" : "leyue.userdatas", "background" : true }, { "v" : 1, "unique" : true, "key" : { "age" : -1 }, "name" : "ageIndex", "ns" : "leyue.userdatas", "sparse" : true } ] // 插入一個(gè)已存在的age db.userdatas.insert({ "name" : "u8", "age" : 32}) WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error index: leyue.userdatas.$ageIndex dup key: { : 32.0 }" } })
創(chuàng)建復(fù)合索引
db.userdatas.createIndex({"name":1,"age":-1}) db.userdatas.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.userdatas" }, { "v" : 1, "key" : { "name" : 1, "age" : -1 }, "name" : "name_1_age_-1", "ns" : "leyue.userdatas" } ]
所有的字段都存在集合 system.indexes 中
db.system.indexes.find() { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.userdatas" } { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.scores" } { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.test" } { "v" : 1, "key" : { "user" : 1, "name" : 1 }, "name" : "myindex", "ns" : "leyue.test" } { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "leyue.mycapped" } { "v" : 1, "key" : { "user" : 1 }, "name" : "user_1", "ns" : "leyue.test" } { "v" : 1, "key" : { "name" : 1 }, "name" : "myindex", "ns" : "leyue.userdatas" }
索引總結(jié)
1:創(chuàng)建索引時(shí),1表示按升序存儲(chǔ),-1表示按降序存儲(chǔ)。
2:可以創(chuàng)建復(fù)合索引,如果想用到復(fù)合索引,必須在查詢條件中包含復(fù)合索引中的前N個(gè)索引列
3: 如果查詢條件中的鍵值順序和復(fù)合索引中的創(chuàng)建順序不一致的話,
MongoDB可以智能的幫助我們調(diào)整該順序,以便使復(fù)合索引可以為查詢所用。
4: 可以為內(nèi)嵌文檔創(chuàng)建索引,其規(guī)則和普通文檔創(chuàng)建索引是一樣的。
5: 一次查詢中只能使用一個(gè)索引,$or特殊,可以在每個(gè)分支條件上使用一個(gè)索引。
6: $where,$exists不能使用索引,還有一些低效率的操作符,比如:$ne,$not,$nin等。
7: 設(shè)計(jì)多個(gè)字段的索引時(shí),應(yīng)該盡量將用于精確匹配的字段放在索引的前面。
explain 使用
語法
db.collection.explain().<method(...)>
explain() 可以設(shè)置參數(shù) :
- queryPlanner。
- executionStats。
- allPlansExecution。
示例
for(var i=0;i<100000;i++) { db.test.insert({"user":"user"+i}); }
沒有使用索引
db.test.explain("executionStats").find({"user":"user200000"}) { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "leyue.test", "indexFilterSet" : false, "parsedQuery" : { "user" : { "$eq" : "user200000" } }, "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "user" : { "$eq" : "user200000" } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "executionStats" : { "executionSuccess" : true, "nReturned" : 2, "executionTimeMillis" : 326, "totalKeysExamined" : 0, "totalDocsExamined" : 1006497, "executionStages" : { "stage" : "COLLSCAN", "filter" : { "user" : { "$eq" : "user200000" } }, "nReturned" : 2, "executionTimeMillisEstimate" : 270, "works" : 1006499, "advanced" : 2, "needTime" : 1006496, "needYield" : 0, "saveState" : 7863, "restoreState" : 7863, "isEOF" : 1, "invalidates" : 0, "direction" : "forward", "docsExamined" : 1006497 } }, "serverInfo" : { "host" : "lihaodeMacBook-Pro.local", "port" : 27017, "version" : "3.2.1", "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2" }, "ok" : 1 }
executionStats.executionTimeMillis: query
的整體查詢時(shí)間。executionStats.nReturned
: 查詢返回的條目。executionStats.totalKeysExamined
: 索引掃描條目。executionStats.totalDocsExamined
: 文檔掃描條目。
executionTimeMillis = 326
query 執(zhí)行時(shí)間
nReturned=2
返回兩條數(shù)據(jù)
totalKeysExamined=0
沒有用到索引
totalDocsExamined 全文檔掃描
理想狀態(tài):
nReturned=totalKeysExamined & totalDocsExamined=0
Stage狀態(tài)分析
stage | 描述 |
---|---|
COLLSCAN | 全表掃描 |
IXSCAN | 掃描索引 |
FETCH | 根據(jù)索引去檢索指定document |
SHARD_MERGE | 將各個(gè)分片返回?cái)?shù)據(jù)進(jìn)行merge |
SORT | 表明在內(nèi)存中進(jìn)行了排序 |
LIMIT | 使用limit限制返回?cái)?shù) |
SKIP | 使用skip進(jìn)行跳過 |
IDHACK | 針對(duì)_id進(jìn)行查詢 |
SHARDING_FILTER | 通過mongos對(duì)分片數(shù)據(jù)進(jìn)行查詢 |
COUNT | 利用db.coll.explain().count()之類進(jìn)行count運(yùn)算 |
COUNTSCAN | count不使用Index進(jìn)行count時(shí)的stage返回 |
COUNT_SCAN | count使用了Index進(jìn)行count時(shí)的stage返回 |
SUBPLA | 未使用到索引的$or查詢的stage返回 |
TEXT | 使用全文索引進(jìn)行查詢時(shí)候的stage返回 |
PROJECTION | 限定返回字段時(shí)候stage的返回 |
對(duì)于普通查詢,我希望看到stage的組合(查詢的時(shí)候盡可能用上索引):
Fetch+IDHACK
Fetch+ixscan
Limit+(Fetch+ixscan)
PROJECTION+ixscan
SHARDING_FITER+ixscan
COUNT_SCAN
不希望看到包含如下的stage:
COLLSCAN(全表掃描),SORT(使用sort但是無index),不合理的SKIP,SUBPLA(未用到index的$or),COUNTSCAN(不使用index進(jìn)行count)
使用索引
db.test.createIndex({"user":1},{"name":"myindex","background":true}) db.test.explain("executionStats").find({"user":"user200000"}) { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "leyue.test", "indexFilterSet" : false, "parsedQuery" : { "user" : { "$eq" : "user200000" } }, "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "user" : 1 }, "indexName" : "myindex", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "user" : [ "[\"user200000\", \"user200000\"]" ] } } }, "rejectedPlans" : [ ] }, "executionStats" : { "executionSuccess" : true, "nReturned" : 2, "executionTimeMillis" : 0, "totalKeysExamined" : 2, "totalDocsExamined" : 2, "executionStages" : { "stage" : "FETCH", "nReturned" : 2, "executionTimeMillisEstimate" : 0, "works" : 3, "advanced" : 2, "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "docsExamined" : 2, "alreadyHasObj" : 0, "inputStage" : { "stage" : "IXSCAN", "nReturned" : 2, "executionTimeMillisEstimate" : 0, "works" : 3, "advanced" : 2, "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "keyPattern" : { "user" : 1 }, "indexName" : "myindex", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "user" : [ "[\"user200000\", \"user200000\"]" ] }, "keysExamined" : 2, "dupsTested" : 0, "dupsDropped" : 0, "seenInvalidated" : 0 } } }, "serverInfo" : { "host" : "lihaodeMacBook-Pro.local", "port" : 27017, "version" : "3.2.1", "gitVersion" : "a14d55980c2cdc565d4704a7e3ad37e4e535c1b2" }, "ok" : 1 }
executionTimeMillis: 0
totalKeysExamined: 2
totalDocsExamined:2
nReturned:2
stage:IXSCAN
使用索引和不使用差距很大,合理使用索引,一個(gè)集合適合做 4-5 個(gè)索引。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
http://www.mongoing.com/eshu_explain3
https://docs.mongodb.com/v3.2/reference/explain-results/#queryplanner
- MongoDB索引使用詳解
- MongoDB的基礎(chǔ)查詢和索引操作方法總結(jié)
- MongoDB性能篇之創(chuàng)建索引,組合索引,唯一索引,刪除索引和explain執(zhí)行計(jì)劃
- MongoDB中創(chuàng)建索引需要注意的事項(xiàng)
- pymongo給mongodb創(chuàng)建索引的簡單實(shí)現(xiàn)方法
- MongoDB查詢字段沒有創(chuàng)建索引導(dǎo)致的連接超時(shí)異常解案例分享
- MongoDB學(xué)習(xí)筆記(六) MongoDB索引用法和效率分析
- mongodb處理中文索引與查找字符串詳解
- pymongo為mongodb數(shù)據(jù)庫添加索引的方法
- MongoDB數(shù)據(jù)庫中索引(index)詳解
- Mongodb索引的優(yōu)化
- MongoDB入門教程之索引操作淺析
- MongoDB教程之索引介紹
- MongoDB的索引
- mongodb索引知識(shí)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- MongoDB TTL索引的實(shí)例詳解
- 基于MongoDB數(shù)據(jù)庫索引構(gòu)建情況全面分析
- 關(guān)于MongoDB索引管理-索引的創(chuàng)建、查看、刪除操作詳解
相關(guān)文章
MongoDB中javascript腳本編程簡介和入門實(shí)例
作為一個(gè)數(shù)據(jù)庫,MongoDB有一個(gè)很大的優(yōu)勢——它使用js管理數(shù)據(jù)庫,所以也能夠使用js腳本進(jìn)行復(fù)雜的管理——這種方法非常靈活2014-04-04關(guān)于MongoDB數(shù)據(jù)庫核心概念
這篇文章主要介紹了關(guān)于MongoDB數(shù)據(jù)庫核心概念,MongoDB由C++語言編寫,是一個(gè)基于分布式文件存儲(chǔ)的開源數(shù)據(jù)庫系統(tǒng),需要的朋友可以參考下2023-04-04MongoDB安裝、基礎(chǔ)操作和聚合實(shí)例介紹
雖然MongoDB這些年很流行,但筆者之前沒研究過,現(xiàn)在有需求研究這類NoSQL的數(shù)據(jù)庫,是為了驗(yàn)證其是否可被替換,本文給大家介紹MongoDB安裝、基礎(chǔ)操作和聚合實(shí)例詳解,感興趣的朋友一起看看吧2024-07-07MongoDB中數(shù)據(jù)的替換方法實(shí)現(xiàn)類Replace()函數(shù)功能詳解
這篇文章主要介紹了MongoDB中數(shù)據(jù)的替換方法實(shí)現(xiàn)類Replace()函數(shù)功能詳解,需要的朋友可以參考下2020-02-02Mongodb過濾器filter選擇要返回的數(shù)組子集操作方法
Mongodb使用過濾器 $filter根據(jù)指定條件選擇要返回的數(shù)組子集,這篇文章主要介紹了Mongodb對(duì)嵌套文檔數(shù)組進(jìn)行查詢操作,需要的朋友可以參考下2023-07-07Windows下MongoDB的下載安裝、環(huán)境配置教程圖解
這篇文章主要介紹了Windows下MongoDB的下載安裝、環(huán)境配置教程詳解,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-06-06關(guān)于對(duì)MongoDB索引的一些簡單理解
索引的作用是為了提升查詢效率,如果查詢條件帶有索引,MongoDB 將掃描索引, 通過索引確定要查詢的部分文檔,而非直接對(duì)全部文檔進(jìn)行掃描,下面這篇文章主要給大家介紹了關(guān)于對(duì)MongoDB索引的一些簡單理解,需要的朋友可以參考下2021-09-09