mongodb索引講解與優(yōu)化

語句集合

語句 功能 備注
db.name. getIndexes() 查詢索引
db.name.totalIndexSize() 查詢索引大小
db.name.dropIndex("indexName") 刪除索引
db.name.dropIndex(‘*’) 刪除name集合中的所有索引 _id索引不會刪除
沒有修改索引的方法 如果想想修改索引 先刪除舊索引,再重新創(chuàng)建索引
db.name.ensureIndex() 創(chuàng)建索引

索引種類

種類 解釋 備注
默認索引 Mongodb每個collection都會有一個默認主鍵_id,這個不能刪除、也不會更名。當collection創(chuàng)建后,系統(tǒng)會自動創(chuàng)建一個”id”的索引,這個也是無法刪除與更名的
單列索引 在單個欄位上創(chuàng)建的索引 eg:需要對Mail的read創(chuàng)建升序索引:db.Mail.ensureIndex({‘read’:1})
組合索引 對多個鍵創(chuàng)建的索引 eg:需要對Mail的user與folderId創(chuàng)建降序索引:db.Mail.ensureIndex({‘user’:-1,’folderId’:-1})
子文檔索引 可以為內(nèi)嵌文檔的鍵創(chuàng)建索引,這種與普通索引沒有什么區(qū)別 eg:需要對Mail中的attachments下的filename創(chuàng)建索引: db.Mail.ensureIndex({‘a(chǎn)ttachments.filename’:1})
注意:attachments.filename必須位于’’之中,否則會報錯
唯一索引 唯 一索引可能確保collection的每一個document指定的鍵的唯一性。當文檔不存在指定鍵時,會被認為鍵值是“null”,所以“null”也 會被認為是重復的,所以一般被作為唯一索引的鍵,最好都要有鍵值對 要保證Mail中每個用戶的mailfilename的唯一性:db.Mail.ensureIndex({‘user’:1,‘filename’:1},{name:’index1’,‘unique’:true})

當為已有的collection增加唯一索引時,可能會有數(shù)據(jù)已經(jīng)重復了。有時候可能希望將所有包含重復的文檔都刪除,可能在創(chuàng)建唯一索引時,使用dropDups選項:
db.Mail.ensureIndex({‘user’:1,‘filename’:1},{‘unique’:true,’dropDups’:true})
這個會將重復的數(shù)據(jù)只保留一份,不過有點魯莽,如果數(shù)據(jù)很重要的話,建議不好這樣做。

注意了:
Insert并不檢查文檔是否插入過,所以確保數(shù)據(jù)的唯一性,可能要用安全模式插入才行。這樣,在插入時,如果有重復就會有錯誤提醒
Sparse索引 Sparse index解決索引文件過大的問題,有時候我們要索引的某個屬性并非是所有記錄都有,普通的索引是將所有的記錄都包含進來,而sparse索引則僅包含含 有這個屬性的記錄,它不會對該項值為空的行作索引。這樣就大大減小了某些列的索引大小。目前的限制是,sparse index只能包含一個屬性。 eg:在Mail中有個標簽屬性labels,這個屬性是唯一的,且有值的情況也不多,這種情況就最適合用sparse索引 了,創(chuàng)建索引的命令為:
db.Mail.ensureIndex({labels:1},{sparse:true})
Covered 索引 如果你查找的值正好是在索引中,則可以直接返回索引中存的值,而不用到數(shù)據(jù)文件中查找。(這個在傳統(tǒng)關系型數(shù)據(jù)庫中也有實現(xiàn)),不過,必須滿足以下條件:
1:必須提供準備的返回字段,以便可以直接從索引庫中查詢
2:必須明確地排除使用_id字段{_id:0}當用explain時,當indexOnly=true,表示有用到covered index
// do a login with a covered index, returning the users roles/groups
> db.users.ensureIndex( { username : 1, password : 1, roles : 1} );
> db.users.save({username: "joe", password: "pass", roles: 2})
> db.users.save({username: "liz", password: "pass2", roles: 4})
> db.users.find({username: "joe"}, {_id: 0, roles: 1})
{ "roles" : 2 }
> db.users.find({username: "joe"}, {_id: 0, roles: 1}).explain()
{
"cursor" : "BtreeCursor username_1_password_1_roles_1",
...
"indexOnly" : true,
...
}

索引觸發(fā)條件

索引命中:

假設索引為:

{a:1,b:1,c:1,d:1}:

實際上是有了下列索引

{a:1},{a:1,b:1},{a:1,b:1,c:1},{a:1,b:1,c:1,d:1}

但是使用{b:1}、{a:1,c:1}等索引的查詢是會被優(yōu)化的,只有使用索引前部的查詢才能使用該索引。

Mongodb的查詢優(yōu)化器會重排查詢項的順序,以便命中索引,比如:查詢{x:’a’,y:’b’}的時候,如果已有了{y:1,x:1}的索引,mongodb也會自己找到并命中的。

創(chuàng)建索引的缺點是每次插入、更新與刪除時都會產(chǎn)生額外的開銷,這是因為數(shù)據(jù)庫不但需要執(zhí)行這些操作,還是處理索引,因些,要盡量可能少創(chuàng)建索引。每個集合默認的最大索引個數(shù)為64個。

查詢時,不要使用$ne or $nin,這樣不能命中索引

使用explain查看

新版explain使用說明

db.collection.find(query).explain();

返回的信息如下

{“cursor” : “BasicCursor”,

“indexBounds” : [ ],

“nscanned” : 57594,

“nscannedObjects” : 57594,

“nYields” : 2 ,

“n” : 3 ,

“millis” : 108,

“indexOnly” : false}

現(xiàn)實結(jié)果可以得知cursor的類型,DB掃描的數(shù)據(jù)數(shù),返回的數(shù)據(jù)數(shù),還有執(zhí)行的毫秒數(shù)。

“cursor” : “BasicCursor”:

命中的索引,當為BasicCursor時表示沒有命中任何索引

indexBounds: 所使用的索引,被設置為表示為索引掃描的關鍵邊界。

nscanned – 掃描的數(shù)據(jù)條數(shù)。

nscannedObjects – 掃描對象的數(shù)。

nYields – 查詢所產(chǎn)生的鎖的個數(shù)。

isMultiKey- MongoDB中提供了可以自動索引數(shù)組對象的值

If true, a multikey index was used.

n- 返回文檔的數(shù)量

millis- 數(shù)據(jù)庫中執(zhí)行查詢的時間

indexOnly – 是否使用了covered index。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容