摘要:所以,如果你很少對集合進(jìn)行讀取操作,建議不使用索引內(nèi)存使用由于索引是存儲(chǔ)在內(nèi)存中你應(yīng)該確保該索引的大小不超過內(nèi)存的限制。如果索引的大小大于內(nèi)存的限制,會(huì)刪除一些索引,這將導(dǎo)致性能下降。
本文圍繞索引、游標(biāo)兩部分進(jìn)行探索,對MongoDB數(shù)據(jù)庫的索引部分有一個(gè)大概的了解;
索引索引通常能夠極大的提高查詢的效率,如果沒有索引,MongoDB在讀取數(shù)據(jù)時(shí)必須掃描集合中的每個(gè)文件并選取那些符合查詢條件的記錄。這種掃描全集合的查詢效率是非常低的,特別在處理大量的數(shù)據(jù)時(shí),查詢可以要花費(fèi)幾十秒甚至幾分鐘,這對網(wǎng)站的性能是非常致命的。
索引是特殊的數(shù)據(jù)結(jié)構(gòu),索引存儲(chǔ)在一個(gè)易于遍歷讀取的數(shù)據(jù)集合中,索引是對數(shù)據(jù)庫表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu)。索引,從創(chuàng)建的形式上可以分為普通索引、復(fù)合索引、數(shù)組索引、子文檔索引;
應(yīng)該了解的索引限制,
開銷:每個(gè)索引占據(jù)一定的存儲(chǔ)空間,在進(jìn)行插入,更新和刪除操作時(shí)也需要對索引進(jìn)行操作。所以,如果你很少對集合進(jìn)行讀取操作,建議不使用索引;
內(nèi)存(RAM)使用:由于索引是存儲(chǔ)在內(nèi)存中,你應(yīng)該確保該索引的大小不超過內(nèi)存的限制。如果索引的大小大于內(nèi)存的限制,MongoDB會(huì)刪除一些索引,這將導(dǎo)致性能下降。
最大范圍:
(1)集合中索引不能超過 64 個(gè); (2)索引名的長度不能超過 125 個(gè)字符; (3)一個(gè)復(fù)合索引最多可以有 31 個(gè)字段
索引不能被以下的查詢使用;可以調(diào)用explain()方法查看是否使用索引;
(1)正則表達(dá)式及非操作符,如 `$nin`, `$not`, 等 (2)算術(shù)運(yùn)算符,如 `$mod` 等 (3)`$where` 子句操作 創(chuàng)建索引
為集合grade_1_4根據(jù)性別和年齡創(chuàng)建復(fù)合索引:
db.getCollection("grade_1_4").ensureIndex({"sex": 1, "age": 1})
會(huì)得到結(jié)果:
{ "v" : 2, // 索引的版本號(hào)。默認(rèn)的索引版本取決于mongod創(chuàng)建索引時(shí)運(yùn)行的版本 "key" : { "sex" : 1, "age" : 1 }, "name" : "sex_1_age_1", "ns" : "school.grade_1_4" }
說明:基于sex和age的查詢將會(huì)用到該復(fù)合索引,或者是基于sex的查詢也會(huì)用到該索引,但是只是基于age的查詢將不會(huì)用到該復(fù)合索引。因此可以說,如果想用到復(fù)合索引,必須在查詢條件中包含復(fù)合索引中的前N個(gè)索引列。然而如果查詢條件中的鍵值順序和復(fù)合索引中的創(chuàng)建順序不一致的話,MongoDB可以智能的幫助我們調(diào)整該順序,以便使復(fù)合索引可以為查詢所用
如果分別為性別和年齡創(chuàng)建索引:
db.getCollection("grade_1_4").ensureIndex({"sex": 1}) db.getCollection("grade_1_4").ensureIndex({"age": 1})
會(huì)得到這樣的結(jié)果:
{ "v" : 2, "key" : { "sex" : 1 }, "name" : "sex_1", "ns" : "school.grade_1_4" }, { "v" : 2, "key" : { "age" : 1 }, "name" : "age_1", "ns" : "school.grade_1_4" }查看索引
查看集合grade_1_4已經(jīng)創(chuàng)建的索引規(guī)則:
db.getCollection("grade_1_4").getIndexes()
查看集合grade_1_4索引占用內(nèi)存空間的大小,單位是字節(jié):
db.getCollection("grade_1_4").totalIndexSize()刪除索引
刪除集合grade_1_4中name為sex_1的索引規(guī)則:
db.getCollection("grade_1_4").dropIndex({"sex": 1})唯一索引
創(chuàng)建唯一索引與普通索引的區(qū)別在于,多一個(gè)可選參數(shù) unique;舉個(gè)例子,根據(jù)姓名創(chuàng)建唯一索引:
db.getCollection("grade_1_4").ensureIndex({"name":1}, {"unique":true})
創(chuàng)建唯一索引能夠保證每條記錄的name字段值是不重復(fù)的;
當(dāng)一個(gè)文檔以唯一索引的方式保存到集合中去的時(shí)候,任何缺失的索引字段都會(huì)以null值代替,因此,不能在唯一索引上同時(shí)插入兩條缺省的記錄。
假設(shè)集合已經(jīng)存在一些記錄,在些基礎(chǔ)上創(chuàng)建唯一索引;此時(shí),對這些已經(jīng)存在的記錄,如果索引項(xiàng)值是存在重復(fù)的,則創(chuàng)建索引時(shí)會(huì)報(bào)錯(cuò);如果一定要在這樣的鍵上創(chuàng)建唯一索引,那么系統(tǒng)將保存第一條記錄,剩下的記錄會(huì)被刪除,結(jié)合dropDups參數(shù)使用(此參數(shù)只能在mongodb 3.0版本之前使用):
db.getCollection("grade_1_4").ensureIndex({"name":1}, {unique:true, dropDups: true})稀疏索引
稀疏索引的創(chuàng)建和完全索引的創(chuàng)建沒有什么不同。使用稀疏索引進(jìn)行查詢的時(shí)候,某些由于缺失了字段的文檔記錄可能不會(huì)被返回,這是由于稀疏索引子返回被索引了的字段。
示例:
> 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" }性能示例
創(chuàng)建三十萬條數(shù)據(jù)
for (var i = 1; i <= 300000; i++) { db.getCollection("grade_1_5").insert({ "name": "zhangsan" + i, "sex": Math.round(Math.random() * 10) % 2, "age": Math.round(Math.random() * 6) + 3 }); }
根據(jù)姓名查一些特定的人
db.getCollection("grade_1_5").find( { $or: [{"name":"zhangsan10000"},{"name":"zhangsan14000"},{"name":"zhangsan9000"},{"name":"zhangsan23000"},{"name":"zhangsan24050"}, {"name":"zhangsan12000"},{"name":"zhangsan14300"},{"name":"zhangsan9300"},{"name":"zhangsan23300"},{"name":"zhangsan24350"}, {"name":"zhangsan11100"},{"name":"zhangsan15200"},{"name":"zhangsan8100"},{"name":"zhangsan22100"},{"name":"zhangsan26150"}, {"name":"zhangsan10200"},{"name":"zhangsan14020"},{"name":"zhangsan9020"},{"name":"zhangsan23020"},{"name":"zhangsan24070"}, {"name":"zhangsan10300"},{"name":"zhangsan14030"},{"name":"zhangsan9030"},{"name":"zhangsan23030"},{"name":"zhangsan24080"}] } )
對姓名建立索引,會(huì)占用5873664字節(jié)
db.getCollection("grade_1_5").ensureIndex({"name": 1})
對于上面的命令,通過調(diào)整順序,觀察時(shí)間,對性能有一些大概的了解;
行為 | 創(chuàng)建-查詢-建索引 | 創(chuàng)建-建索引-查詢 | 建索引-創(chuàng)建-查詢 |
---|---|---|---|
創(chuàng)建時(shí)間 | 150.957s | 150.957s | 159.967s |
查詢時(shí)間 | 1.024s | 0.005s | 0.005s |
建立索引時(shí)間 | 0.527s | 0.527s | 0.009s |
直接對一個(gè)集合調(diào)用find()方法時(shí),我們會(huì)發(fā)現(xiàn),如果查詢結(jié)果超過二十條,只會(huì)返回二十條的結(jié)果,這是因?yàn)?b>Mongodb會(huì)自動(dòng)遞歸find()返回的是游標(biāo)。
var cursor = db.getCollection("grade_1_4").find({});
執(zhí)行上述命令時(shí),shell并不會(huì)真正地訪問數(shù)據(jù)庫,而是等待開始要求獲得結(jié)果的時(shí)候才向數(shù)據(jù)庫發(fā)送查詢請求。
此時(shí)可以對這個(gè)游標(biāo)進(jìn)行各種設(shè)置,然后調(diào)用游標(biāo)的hashNext()或next()方法,這樣就會(huì)真正訪問數(shù)據(jù)庫,這是一個(gè)懶加載的過程,如下
var cursor = db.getCollection("grade_1_4").find({}); while(cursor.hasNext()){ var doc = cursor.next(); // do stuff with doc };
可以基于游標(biāo),進(jìn)行limit、skip、sort操作,一般應(yīng)用于分頁場景;
limit:限制游標(biāo)返回的數(shù)量,指定了上限;
skip :忽略前面的部分文檔,如果文檔總數(shù)量小于忽略的數(shù)量,則返回空集合;
sort :對得到的子集合進(jìn)行排序,可以按照多個(gè)鍵進(jìn)行正反排序;
上述三個(gè)命令可以進(jìn)行鏈?zhǔn)讲僮鳎?/p> 附錄
以下是文章會(huì)用到的參考,及有意義的擴(kuò)展閱讀;
DrifterJ"s Stash的博客 - 學(xué)習(xí)MongoDB--(4-3):MongoDB查詢(游標(biāo)使用)
MongoDB使用小結(jié):一些不常見的經(jīng)驗(yàn)分享
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/19109.html
摘要:步優(yōu)化以及其它數(shù)據(jù)庫后端掘金原文鏈接在發(fā)表了一篇簡潔有效有趣和令人信服的分鐘教程描述了如何進(jìn)行優(yōu)化。關(guān)于的七種后端掘金對于的,在學(xué)習(xí)起來可能是比較亂的。 5 步優(yōu)化 MongoDB 以及其它數(shù)據(jù)庫 - 后端 - 掘金原文鏈接 Jared Rosoff 在 Scale Out Camp 發(fā)表了一篇簡潔、有效、有趣和令人信服的《8 分鐘 MongoDB 教程》描述了如何進(jìn)行 MongoDB...
摘要:本文的目標(biāo)是通過大量的示例,來更好的理解如果在中進(jìn)行數(shù)據(jù)操作初入客戶端剛利用命令進(jìn)入客戶端環(huán)境,此時(shí)對數(shù)據(jù)庫一無所知舉目四望,想知道現(xiàn)在有哪些數(shù)據(jù)庫,因?yàn)槭切卵b的環(huán)境,所以只看到了和兩個(gè)默認(rèn)就存在的數(shù)據(jù)庫目光慢慢收回,那么當(dāng)前是處于哪個(gè)數(shù)據(jù) 本文的目標(biāo)是通過大量的示例,來更好的理解如果在Mongodb中進(jìn)行數(shù)據(jù)操作; 初入客戶端剛利用 mongod命令進(jìn)入客戶端環(huán)境,此時(shí)對數(shù)據(jù)庫一無所...
摘要:磕磕絆絆,我們的系列教程終于落下帷幕,從月第一篇開始到現(xiàn)在,中間有一段時(shí)間開小差,不過還好沒有爛尾。好了,這里我再把本系列的所有文章羅列出來,以供小伙伴們搜索查看。 磕磕絆絆,我們的MongoDB系列教程終于落下帷幕,從11月21第一篇開始到現(xiàn)在,中間有一段時(shí)間開小差,不過還好沒有爛尾。好了,這里我再把本系列的所有文章羅列出來,以供小伙伴們搜索查看。 1.Linux上安裝Mongo...
摘要:實(shí)例教程是一個(gè)數(shù)據(jù)庫搜云庫教程專注于開發(fā)技術(shù)的研究與知識(shí)分享方法中你也可以設(shè)置使用多個(gè)字段創(chuàng)建索引關(guān)系型數(shù)據(jù)庫中稱作復(fù)合索引。 上一篇文章練習(xí)了,MongoDB 的以下操作 安裝 MongoDB 服務(wù) 連接 MongoDB MongoDB 創(chuàng)建數(shù)據(jù)庫 MongoDB 刪除數(shù)據(jù)庫 MongoDB 插入文檔 MongoDB 刪除文檔 MongoDB 查詢文檔 MongoDB AND 條件...
閱讀 1809·2019-08-30 13:54
閱讀 2725·2019-08-29 17:27
閱讀 1109·2019-08-29 17:23
閱讀 3350·2019-08-29 15:20
閱讀 1225·2019-08-29 11:28
閱讀 1566·2019-08-26 10:39
閱讀 1315·2019-08-26 10:29
閱讀 639·2019-08-26 10:13