索引數據庫
索引一般可以極大的提升查詢的效率。在系統中使用查詢時,應該考慮創建相關的索引。在MongoDB中建立索引相對比較容易。數據結構
MongoDB中的索引在概念上和大多數關係型數據庫如MySQL是同樣的。當你在某種狀況下須要在MySQL中創建索引,這樣的情景一樣適合於MongoDB。app
基本操做函數
索引是一種數據結構,他蒐集一個集合中文檔特定字段的值。MongoDB的查詢優化器可以使用這種數據結構來快速的對集合(collection)中的文檔(collection)進行尋找和排序.準確來講,這些索引是經過B-Tree索引來實現的。post
在命令行中,能夠經過調用ensureIndex()函數來創建索引,該函數指定一個到多個須要索引的字段。沿用在前面的隨筆中的例子,咱們再things集合中的j字段上創建索引:性能
>
db.things.ensureIndex({j:
1
})
EnsureIndex()函數自是在索引不存在的狀況下才會建立。大數據
一旦集合在某一個字段上創建索引後,對該字段的隨機查詢的訪問速度會很快。若是沒有索引,MongoDB會在遍歷全部的鍵值對,而後去對應檢查相關的字段。優化
>
db.things.find({j:
2
});
//
在創建了索引的字段上查詢,速度快
{
"
_id
"
: ObjectId(
"
4e24433dcac1e3490b9033be
"
),
"
x
"
:
4
,
"
j
"
:
2
}
>
db.things.find({x:
3
});
//
在未創建索引的字段上查詢,須要逐個字段匹配,速度慢
{
"
_id
"
: ObjectId(
"
4e244315cac1e3490b9033bc
"
),
"
x
"
:
3
}
經過在命令行中輸入getIndexs()可以查看當前集合中的全部索引。spa
>
db.things.getIndexes()
[
{
"
name
"
:
"
_id_
"
,
"
ns
"
:
"
things.things
"
,
"
key
"
: {
"
_id
"
:
1
},
"
v
"
:
0
},
{
"
_id
"
: ObjectId(
"
4e244382cac1e3490b9033d0
"
ns
"
:
"
things.things
"
,
"
key
"
: {
"
j
"
:
1
},
"
name
"
:
"
j_1
"
,
"
v
"
:
0
}
]
經過db.system.indexes.find()可以返回當前數據庫中的全部索引命令行
>
db.system.indexes.find()
{
"
name
"
:
"
_id_
"
,
"
ns
"
:
"
things.things
"
,
"
key
"
: {
"
_id
"
:
1
},
"
v
"
:
0
}
{
"
_id
"
: ObjectId(
"
4e244382cac1e3490b9033d0
"
),
"
ns
"
:
"
things.things
"
,
"
key
"
:{
"
j
"
:
1
},
"
name
"
:
"
j_1
"
,
"
v
"
:
0
}
默認索引
對於每個集合(除了capped集合),默認會在_id字段上建立索引,並且這個特別的索引不能刪除。_id字段是強制惟一的,由數據庫維護。
嵌套關鍵字
在MongoDB中,甚至可以在一個嵌入的文檔上(embedded)創建索引.
>
db.things.ensureIndex({
"
address.city
"
:
1
})
文檔做爲索引
任何類型,包括文檔(document)都能做爲索引:
>
db.factories.insert({name:
"
xyz
"
,metro:{city:
"
New York
"
,state:
"
NY
"
}});
>
db.factories.ensureIndex({metro:
1
});
>
db.factories.find({metro:{city:
"
New York
"
,state:
"
NY
"
}});
//
可以利用索引進行查詢
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find({metro:{$gte:{city:
"
New York
"
}}});
//
可以利用索引進行查詢
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find({metro:{state:
"
NY
"
,city:
"
New York
"
}})
//
不可以返回結果,字段的順序不對
建立文檔索引的一個替代方法是建立複合索引,例如:
>
db.factories.ensureIndex({
"
metro.city
"
:
1
,
"
metro.state
"
:
1
})
>
db.factories.find({
"
metro.city
"
:
"
New York
"
,
"
metro.state
"
:
"
NY
"
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find({
"
metro.city
"
:
"
New York
"
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find().sort({
"
metro.city
"
:
1
,
"
New York
"
:
1
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find().sort({
"
metro.city
"
:
1
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
組合關鍵字索引
除了基本的以單個關鍵字做爲索引外,MongoDB也支持多個關鍵字的組合索引,和基本的索引同樣,也是用ensureIndex()函數,該函數能夠指定多個鍵。
>
db.things.ensureIndex({j:
1
,name:
-
1
})
當建立索引時,鍵後面的數字代表了索引的方向,取值爲1或者-1,1表示升序,-1表示降序。升序或者降序在隨機訪問的時候關係不大,當時在作排序或者範圍查詢的時候就很重要了。
若是在創建了a,b,c這樣一個複合索引,那麼你能夠在a,
A,b和a,b,c上使用索引查詢。
稀疏索引
和稀疏矩陣相似,稀疏索引就是索引至包含被索引字段的文檔。
任何一個稀疏的缺失某一個字段的文檔將不會存儲在索引中,之因此稱之爲稀疏索引就是說缺失字段的文檔的值會丟失。
稀疏索引的建立和徹底索引的建立沒有什麼不一樣。使用稀疏索引進行查詢的時候,某些因爲缺失了字段的文檔記錄可能不會被返回,這是因爲稀疏索引子返回被索引了的字段。可能比較難以理解,不過看幾個例子就好理解了。
>
db.people.ensureIndex({title:
1
},{sparse:
true
})
//
在title字段上創建稀疏索引
>
db.people.save({name:
"
Jim
"
})
>
db.people.save({name:
"
yang
"
,title:
"
prince
"
})
>
db.people.find();
{
"
_id
"
: ObjectId(
"
4e244dc5cac1e3490b9033d7
"
),
"
name
"
:
"
Jim
"
}
{
"
_id
"
: ObjectId(
"
4e244debcac1e3490b9033d8
"
),
"
name
"
:
"
yang
"
,
"
title
"
:
"
prince
"
}
>
db.people.find().sort({title:
1
})
//
自有包含有索引字段的記錄才被返回
{
"
_id
"
: ObjectId(
"
4e244debcac1e3490b9033d8
"
),
"
name
"
:
"
yang
"
,
"
title
"
:
"
prince
"
}
>
db.people.dropIndex({title:
1
})
//
刪除稀疏索引以後,全部的記錄均顯示
{
"
nIndexesWas
"
:
2
,
"
ok
"
:
1
}
>
db.people.find().sort({title:
1
})
{
"
_id
"
: ObjectId(
"
4e244dc5cac1e3490b9033d7
"
),
"
name
"
:
"
Jim
"
}
{
"
_id
"
: ObjectId(
"
4e244debcac1e3490b9033d8
"
),
"
name
"
:
"
yang
"
,
"
title
"
:
"
prince
"
}
惟一索引
MongoDB支持惟一索引,這使得不能插入在惟一索引項上已經存在的記錄。例如,要保證firstname和lastname都是惟一的,命令以下
> db.things.ensureIndex({firstname:1,lastname:1},{unique:true})
缺失的鍵
當一個文檔以惟一索引的方式保存到集合中去的時候,任何缺失的索引字段都會一null值代替,所以,不能在惟一索引上同時插入兩條缺省的記錄。以下:
>
db.things.ensureIndex({firstname:
1
}, {unique:
true
});
>
db.things.save({lastname:
"
Smith
"
});
>
db.things.save({lastname:
"
Jones
"
});
//
會產生錯誤,由於firstname會有兩個null.
重複值:
惟一索引不可以建立在具備重複值的鍵上,若是你必定要在這樣的鍵上建立,那麼想系統將保存第一條記錄,剩下的記錄會被刪除,只須要在建立索引的時候加上dropDups這個可選項便可
>
db.things.ensureIndex({firstname :
1
}, {unique :
true
, dropDups :
true
})
Dropping Indexes
刪除一個特定集合上的索引:
>
db.collection.dropIndexes();
刪除集合中的某一個索引:
db.collection.dropIndex({x:
1
, y:
-
1
})
也能夠直接執行命令進性刪除
db.runCommand({dropIndexes:
'
foo
'
, index : {y:
1
}})
//
刪除集合foo中{y:1}的索引
//
remove all indexes:
db.runCommand({dropIndexes:
'
foo
'
, index :
'
*
'
})
//
刪除集合foo中全部的索引
重建索引:
能夠所用以下命令重建索引:
db.myCollection.reIndex()
//
same as:
db.runCommand( { reIndex :
'
myCollection
'
} )
一般這是沒必要要的,可是在集合的大小變更很大及集合在磁盤空間上佔用不少空間時重建索引纔有用。對於大數據量的集合來講,重建索引可能會很慢。
注:
-
MongoDB
中索引是大小寫敏感的
-
當更新對象是,只有在索引上的這些key
發生變化時纔會更新。着極大地提升了性能。當對象增加了或者必須移動時,全部的索引必須更新,這回很慢
。
-
索引信息會保存在system.indexes
集合中,
運行
db.system.indexes.find()
可以看到這些示例數據,
-
索引的字段的大小有最大限制,
目前接近800 bytes.
可在大於這個值的字段上創建索引是能夠的,可是該字段不會被索引,這種限制在之後的版本中可能被移除。
索引的性能
索引使得能夠經過關鍵字段獲取數據,可以使得快速查詢和更新數據。
可是,必須注意的是,索引也會在插入和刪除的時候增長一些系統的負擔。往集合中插入數據的時候,索引的字段必須加入到B-Tree中去,所以,索引適合創建在讀遠多於寫的數據集上,對於寫入頻繁的集合,在某些狀況下,索引反而有反作用。不過大多數集合都是讀頻繁的集合,因此集合在大多數狀況下是有用的。
使用sort()而不須要索引
若是數據集合比較小(一般小於4M),使用sort()而不須要創建索引就可以返回數據。在這種狀況下,作好聯合使用limit()和sort();