共計 10135 個字符,預計需要花費 26 分鐘才能閱讀完成。
丸趣 TV 小編給大家分享一下 MongoDB 中索引怎么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
在任何數據庫之中,索引都是一種提升數據庫檢索性能的手段。
MongoDB 數據庫里面依然會存在兩種索引創建:一種是自動創建,另外一種是手工創建。
范例:重新準備一個新的簡單集合。
db.emp.drop();
db.emp.insert({name : 趙一 , sex : 男 , age :30, sal :1000, loc : 北京});
db.emp.insert({name : 錢二 , sex : 女 , age :22, sal :5000, loc : 上海});
db.emp.insert({name : 孫三 , sex : 男 , age :40, sal :2000, loc : 深圳});
db.emp.insert({name : 李四 , sex : 女 , age :30, sal :7000, loc : 北京});
db.emp.insert({name : 周五 , sex : 女 , age :30, sal :6400, loc : 北京});
db.emp.insert({name : 吳六 , sex : 男 , age :30, sal :2500, loc : 重慶});
db.emp.insert({name : 鄭七 , sex : 女 , age :50, sal :4700, loc : 成都});
db.emp.insert({name : 王八 , sex : 男 , age :35, sal :8000, loc : 北京});
此時在 emp 的集合上并沒有去設置任何的索引,可以通過 getIndexes()函數來觀察在 emp 集合中的索引。
范例:查詢默認狀態下 emp 集合的索引內容
db.emp.getIndexes();
[
{
v : 2,
key : {
_id : 1
},
name : _id_ ,
ns : hr.emp
}
]
現在發現會存在有一個“_id”列的索引內容。但是如果要想創建自己的索引,則可以使用如下的語法:
索引創建:db. 集合名稱.createIndex({列:1})
設置的 1 表示索引按照升序的方式進行排序,如果使用降序則使用“-1”
范例:創建一個索引,在 age 字段上設置一個降序索引
db.emp.createIndex({age :-1})
{
createdCollectionAutomatically : false,
numIndexesBefore : 1,
numIndexesAfter : 2,
ok : 1
此時并沒有設置索引的名字,所以名字是自動命名的。命名的規范:“字段名稱_索引的排序模式”
db.emp.getIndexes();
[
{
v : 2,
key : {
_id : 1
},
name : _id_ ,
ns : hr.emp
},
{
v : 2,
key : {
age : -1
},
name : age_-1 ,
ns : hr.emp
}
]
范例:針對于當前的 age 字段上的索引做一個分析
db.emp.find({age :30}).explain(executionStats
{
queryPlanner : {
plannerVersion : 1,
namespace : hr.emp ,
indexFilterSet : false,
parsedQuery : {
age : {
$eq : 30
}
},
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 : [
[30.0, 30.0]
]
}
}
},
rejectedPlans : []
},
executionStats : {
executionSuccess : true,
nReturned : 4,
executionTimeMillis : 0,
totalKeysExamined : 4,
totalDocsExamined : 4,
executionStages : {
stage : FETCH ,
nReturned : 4,
executionTimeMillisEstimate : 0,
works : 5,
advanced : 4,
needTime : 0,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
docsExamined : 4,
alreadyHasObj : 0,
inputStage : {
stage : IXSCAN ,
nReturned : 4,
executionTimeMillisEstimate : 0,
works : 5,
advanced : 4,
needTime : 0,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
keyPattern : {
age : -1
},
indexName : age_-1 ,
isMultiKey : false,
multiKeyPaths : {
age : []
},
isUnique : false,
isSparse : false,
isPartial : false,
indexVersion : 2,
direction : forward ,
indexBounds : {
age : [
[30.0, 30.0]
]
},
keysExamined : 4,
seeks : 1,
dupsTested : 0,
dupsDropped : 0,
seenInvalidated : 0
}
}
},
serverInfo : {
host : D2-LZY245 ,
port : 27017,
version : 3.4.7 ,
gitVersion : cf38c1b8a0a8dca4a11737581beafef4fe120bcd
},
ok : 1
}
此時的查詢使用了索引的技術,但是下面再來觀察一個查詢,不使用索引字段
范例:針對于 sal 字段進行查詢
db.emp.find({sal :{ $gt :5000}}).explain(executionStats
{
queryPlanner : {
plannerVersion : 1,
namespace : hr.emp ,
indexFilterSet : false,
parsedQuery : {
sal : {
$gt : 5000
}
},
winningPlan : {
stage : COLLSCAN ,
filter : {
sal : {
$gt : 5000
}
},
direction : forward
},
rejectedPlans : []
},
executionStats : {
executionSuccess : true,
nReturned : 3,
executionTimeMillis : 0,
totalKeysExamined : 0,
totalDocsExamined : 8,
executionStages : {
stage : COLLSCAN ,
filter : {
sal : {
$gt : 5000
}
},
nReturned : 3,
executionTimeMillisEstimate : 0,
works : 10,
advanced : 3,
needTime : 6,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
direction : forward ,
docsExamined : 8
}
},
serverInfo : {
host : D2-LZY245 ,
port : 27017,
version : 3.4.7 ,
gitVersion : cf38c1b8a0a8dca4a11737581beafef4fe120bcd
},
ok : 1
}
此時在 sal 字段上并沒有設置索引,所以當前的索引形式就變成了全集合掃描的模式。
但是如果說,現在換一種形式,年齡和薪水一起執行查詢:
db.emp.find({age :30, sal :7000}).explain(executionStats)
{
queryPlanner : {
plannerVersion : 1,
namespace : hr.emp ,
indexFilterSet : false,
parsedQuery : {
$and : [
{
age : {
$eq : 30
}
},
{
sal : {
$eq : 7000
}
}
]
},
winningPlan : {
stage : FETCH ,
filter : {
sal : {
$eq : 7000
}
},
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 : [
[30.0, 30.0]
]
}
}
},
rejectedPlans : []
},
executionStats : {
executionSuccess : true,
nReturned : 1,
executionTimeMillis : 0,
totalKeysExamined : 4,
totalDocsExamined : 4,
executionStages : {
stage : FETCH ,
filter : {
sal : {
$eq : 7000
}
},
nReturned : 1,
executionTimeMillisEstimate : 0,
works : 5,
advanced : 1,
needTime : 3,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
docsExamined : 4,
alreadyHasObj : 0,
inputStage : {
stage : IXSCAN ,
nReturned : 4,
executionTimeMillisEstimate : 0,
works : 5,
advanced : 4,
needTime : 0,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
keyPattern : {
age : -1
},
indexName : age_-1 ,
isMultiKey : false,
multiKeyPaths : {
age : []
},
isUnique : false,
isSparse : false,
isPartial : false,
indexVersion : 2,
direction : forward ,
indexBounds : {
age : [
[30.0, 30.0]
]
},
keysExamined : 4,
seeks : 1,
dupsTested : 0,
dupsDropped : 0,
seenInvalidated : 0
}
}
},
serverInfo : {
host : D2-LZY245 ,
port : 27017,
version : 3.4.7 ,
gitVersion : cf38c1b8a0a8dca4a11737581beafef4fe120bcd
},
ok : 1
}
這個時候雖然 age 字段上面存在索引,由于 sal 字段上面沒有索引,所以依然使用的是全表掃描操作。為了解決此時的問題,可以使用一個復合索引。
db.emp.createIndex({age :-1, sal :-1},{name: age_-1_sal_-1_index})
{
createdCollectionAutomatically : false,
numIndexesBefore : 2,
numIndexesAfter : 3,
ok : 1
}
范例:默認使用索引
db.emp.find({age :30, sal :7000}).explain(executionStats)
{
queryPlanner : {
plannerVersion : 1,
namespace : hr.emp ,
indexFilterSet : false,
parsedQuery : {
$and : [
{
age : {
$eq : 30
}
},
{
sal : {
$eq : 7000
}
}
]
},
winningPlan : {
stage : FETCH ,
inputStage : {
stage : IXSCAN ,
keyPattern : {
age : -1,
sal : -1
},
indexName : age_-1_sal_-1_index ,
isMultiKey : false,
multiKeyPaths : {
age : [],
sal : []
},
isUnique : false,
isSparse : false,
isPartial : false,
indexVersion : 2,
direction : forward ,
indexBounds : {
age : [
[30.0, 30.0]
],
sal : [
[7000.0, 7000.0]
]
}
}
},
rejectedPlans : [
{
stage : FETCH ,
filter : {
sal : {
$eq : 7000
}
},
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 : [
[30.0, 30.0]
]
}
}
}
]
},
executionStats : {
executionSuccess : true,
nReturned : 1,
executionTimeMillis : 0,
totalKeysExamined : 1,
totalDocsExamined : 1,
executionStages : {
stage : FETCH ,
nReturned : 1,
executionTimeMillisEstimate : 0,
works : 3,
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 : {
age : -1,
sal : -1
},
indexName : age_-1_sal_-1_index ,
isMultiKey : false,
multiKeyPaths : {
age : [],
sal : []
},
isUnique : false,
isSparse : false,
isPartial : false,
indexVersion : 2,
direction : forward ,
indexBounds : {
age : [
[30.0, 30.0]
],
sal : [
[7000.0, 7000.0]
]
},
keysExamined : 1,
seeks : 1,
dupsTested : 0,
dupsDropped : 0,
seenInvalidated : 0
}
}
},
serverInfo : {
host : D2-LZY245 ,
port : 27017,
version : 3.4.7 ,
gitVersion : cf38c1b8a0a8dca4a11737581beafef4fe120bcd
},
ok : 1
}
但是如果換到了以下條件:
db.emp.find({$or :[{ age :{ $gt :30}},{sal :{ $gt :5000}}]}).explain(executionStats)
{
queryPlanner : {
plannerVersion : 1,
namespace : hr.emp ,
indexFilterSet : false,
parsedQuery : {
$or : [
{
age : {
$gt : 30
}
},
{
sal : {
$gt : 5000
}
}
]
},
winningPlan : {
stage : SUBPLAN ,
inputStage : {
stage : COLLSCAN ,
filter : {
$or : [
{
age : {
$gt : 30
}
},
{
sal : {
$gt : 5000
}
}
]
},
direction : forward
}
},
rejectedPlans : []
},
executionStats : {
executionSuccess : true,
nReturned : 5,
executionTimeMillis : 0,
totalKeysExamined : 0,
totalDocsExamined : 8,
executionStages : {
stage : SUBPLAN ,
nReturned : 5,
executionTimeMillisEstimate : 0,
works : 10,
advanced : 5,
needTime : 4,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
inputStage : {
stage : COLLSCAN ,
filter : {
$or : [
{
age : {
$gt : 30
}
},
{
sal : {
$gt : 5000
}
}
]
},
nReturned : 5,
executionTimeMillisEstimate : 0,
works : 10,
advanced : 5,
needTime : 4,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
direction : forward ,
docsExamined : 8
}
}
},
serverInfo : {
host : D2-LZY245 ,
port : 27017,
version : 3.4.7 ,
gitVersion : cf38c1b8a0a8dca4a11737581beafef4fe120bcd
},
ok : 1
}
現在發現并沒有使用索引,所以這個時候看能否強制使用一次索引:hint()函數為強制使用索引操作。
范例:強制使用索引
db.emp.find({$or :[{ age :{ $gt :50}},{sal :{ $gt :3000}}]}).hint(age_-1_sal_-1_index).explain(executionStats)
{
queryPlanner : {
plannerVersion : 1,
namespace : hr.emp ,
indexFilterSet : false,
parsedQuery : {
$or : [
{
age : {
$gt : 50
}
},
{
sal : {
$gt : 3000
}
}
]
},
winningPlan : {
stage : FETCH ,
filter : {
$or : [
{
age : {
$gt : 50
}
},
{
sal : {
$gt : 3000
}
}
]
},
inputStage : {
stage : IXSCAN ,
keyPattern : {
age : -1,
sal : -1
},
indexName : age_-1_sal_-1_index ,
isMultiKey : false,
multiKeyPaths : {
age : [],
sal : []
},
isUnique : false,
isSparse : false,
isPartial : false,
indexVersion : 2,
direction : forward ,
indexBounds : {
age : [
[MaxKey, MinKey]
],
sal : [
[MaxKey, MinKey]
]
}
}
},
rejectedPlans : []
},
executionStats : {
executionSuccess : true,
nReturned : 5,
executionTimeMillis : 0,
totalKeysExamined : 8,
totalDocsExamined : 8,
executionStages : {
stage : FETCH ,
filter : {
$or : [
{
age : {
$gt : 50
}
},
{
sal : {
$gt : 3000
}
}
]
},
nReturned : 5,
executionTimeMillisEstimate : 0,
works : 9,
advanced : 5,
needTime : 3,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
docsExamined : 8,
alreadyHasObj : 0,
inputStage : {
stage : IXSCAN ,
nReturned : 8,
executionTimeMillisEstimate : 0,
works : 9,
advanced : 8,
needTime : 0,
needYield : 0,
saveState : 0,
restoreState : 0,
isEOF : 1,
invalidates : 0,
keyPattern : {
age : -1,
sal : -1
},
indexName : age_-1_sal_-1_index ,
isMultiKey : false,
multiKeyPaths : {
age : [],
sal : []
},
isUnique : false,
isSparse : false,
isPartial : false,
indexVersion : 2,
direction : forward ,
indexBounds : {
age : [
[MaxKey, MinKey]
],
sal : [
[MaxKey, MinKey]
]
},
keysExamined : 8,
seeks : 1,
dupsTested : 0,
dupsDropped : 0,
seenInvalidated : 0
}
}
},
serverInfo : {
host : D2-LZY245 ,
port : 27017,
version : 3.4.7 ,
gitVersion : cf38c1b8a0a8dca4a11737581beafef4fe120bcd
},
ok : 1
}
如果正常來講,這個代碼根本就不可能調用默認的索引執行,如果需要可以使用 hint()函數強制 MongoDB 必須使用索引。
如果在一個集合里面設置了過多的索引,實際上會導致性能下降。那么可以刪除索引。
范例:刪除一個索引
db.emp.dropIndex(age_-1_sal_-1_index)
{nIndexesWas : 3, ok : 1}
db.emp.getIndexes();
[
{
v : 2,
key : {
_id : 1
},
name : _id_ ,
ns : hr.emp
},
{
v : 2,
key : {
age : -1
},
name : age_-1 ,
ns : hr.emp
}
]
范例:刪除非 _id 的索引,也就是自定義的索引
db.emp.dropIndexes();
{
nIndexesWas : 2,
msg : non-_id indexes dropped for collection ,
ok : 1
}
db.emp.getIndexes();
[
{
v : 2,
key : {
_id : 1
},
name : _id_ ,
ns : hr.emp
}
]
以上是“MongoDB 中索引怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道!