亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MongoDB > 正文

MongoDB索引使用詳解

2020-03-14 13:17:50
字體:
來源:轉載
供稿:網友
索引,使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓名(name)列。如果要按姓查找特定職員,與必須搜索表中的所有行相比,索引會幫助您更快地獲得該信息。
 

索引就像書的目錄,如果查找某內容在沒有目錄的幫助下,只能全篇查找翻閱,這導致效率非常的低下;如果在借助目錄情況下,就能很快的定位具體內容所在區域,效率會直線提高。

索引簡介

首先打開命令行,輸入mongo。默認mongodb會連接名為test的數據庫。

? ~ mongoMongoDB shell version: 2.4.9connecting to: test> show collections> 

可以使用show collections/tables查看數據庫為空。

然后在mongodb命令行終端執行如下代碼

> for(var i=0;i<100000;i++) {... db.users.insert({username:'user'+i})... }> show collectionssystem.indexesusers> 

再查看數據庫發現多了system.indexes 和 users兩個表,前者即所謂的索引,后者為新建的數據庫表。
這樣user表中即有了10萬條數據。

> db.users.find(){ "_id" : ObjectId("5694d5da8fad9e319c5b43e4"), "username" : "user0" }{ "_id" : ObjectId("5694d5da8fad9e319c5b43e5"), "username" : "user1" }{ "_id" : ObjectId("5694d5da8fad9e319c5b43e6"), "username" : "user2" }{ "_id" : ObjectId("5694d5da8fad9e319c5b43e7"), "username" : "user3" }{ "_id" : ObjectId("5694d5da8fad9e319c5b43e8"), "username" : "user4" }{ "_id" : ObjectId("5694d5da8fad9e319c5b43e9"), "username" : "user5" }

現在需要查找其中任意一條數據,比如

> db.users.find({username: 'user1234'}){ "_id" : ObjectId("5694d5db8fad9e319c5b48b6"), "username" : "user1234" }

發現這條數據成功找到,但需要了解詳細信息,需要加上explain方法

> db.users.find({username: 'user1234'}).explain(){  "cursor" : "BasicCursor",  "isMultiKey" : false,  "n" : 1,  "nscannedObjects" : 100000,  "nscanned" : 100000,  "nscannedObjectsAllPlans" : 100000,  "nscannedAllPlans" : 100000,  "scanAndOrder" : false,  "indexOnly" : false,  "nYields" : 0,  "nChunkSkips" : 0,  "millis" : 30,  "indexBounds" : {      },  "server" : "root:27017"}

參數很多,目前我們只關注其中的"nscanned" : 100000和"millis" : 30這兩項。

nscanned表示mongodb在完成這個查詢過程中掃描的文檔總數??梢园l現,集合中的每個文檔都被掃描了,并且總時間為30毫秒。

如果數據有1000萬個,如果每次查詢文檔都遍歷一遍。呃,時間也是相當可觀。

對于此類查詢,索引是一個非常好的解決方案。

> db.users.ensureIndex({"username": 1})

然后再查找user1234

> db.users.ensureIndex({"username": 1})> db.users.find({username: 'user1234'}).explain(){  "cursor" : "BtreeCursor username_1",  "isMultiKey" : false,  "n" : 1,  "nscannedObjects" : 1,  "nscanned" : 1,  "nscannedObjectsAllPlans" : 1,  "nscannedAllPlans" : 1,  "scanAndOrder" : false,  "indexOnly" : false,  "nYields" : 0,  "nChunkSkips" : 0,  "millis" : 0,  "indexBounds" : {    "username" : [      [        "user1234",        "user1234"      ]    ]  },  "server" : "root:27017"}

的確有點不可思議,查詢在瞬間完成,因為通過索引只查找了一條數據,而不是100000條。

當然使用索引是也是有代價的:對于添加的每一條索引,每次寫操作(插入、更新、刪除)都將耗費更多的時間。這是因為,當數據發生變化時,不僅要更新文檔,還要更新級集合上的所有索引。因此,mongodb限制每個集合最多有64個索引。通常,在一個特定的集合上,不應該擁有兩個以上的索引。

小技巧

如果一個非常通用的查詢,或者這個查詢造成了性能瓶頸,那么在某字段(比如username)建立索引是非常好的選擇。但只是給管理員用的查詢(不太在意查詢耗費時間),就不該對這個字段建立索引。

復合索引

索引的值是按一定順序排列的,所以使用索引鍵對文檔進行排序非??臁?/p>

db.users.find().sort({'age': 1, 'username': 1})

這里先根據age排序再根據username排序,所以username在這里發揮的作用并不大。為了優化這個排序,可能需要在age和username上建立索引。

db.users.ensureIndex({'age':1, 'username': 1})
這就建立了一個復合索引(建立在多個字段上的索引),如果查詢條件包括多個鍵,這個索引就非常有用。

建立復合索引后,每個索引條目都包括一個age字段和一個username字段,并且指向文檔在磁盤上的存儲位置。
此時,age字段是嚴格升序排列的,如果age相等時再按照username升序排列。

查詢方式

點查詢(point query)

用于查詢單個值(盡管包含這個值的文檔可能有多個)

db.users.find({'age': 21}).sort({'username': -1})

因為我們已經建立好復合索引,一個age一個username,建立索引時使用的是升序排序(即數字1),當使用點查詢查找{age:21},假設仍然是10萬條數據,可能年齡是21的很多人,因此會找到不只一條數據。然后sort({'username': -1})會對這些數據進行逆序排序,本意是這樣。但我們不要忘記建立索引時'username':1是升序(從小到大),如果想得到逆序只要對數據從最后一個索引開始,依次遍歷即可得到想要的結果。

排序方向并不重要,mongodb可以從任意方向對索引進行遍歷。
綜上,復合索引在點查詢這種情況非常高效,直接定位年齡,不需要對結果進行排序,返回結果。

多值查詢(multi-value-query)

db.users.find({'age': {"$gte": 21, "$lte": 30}})

查找多個值相匹配的文檔。多值查詢也可以理解為多個點查詢。
如上,要查找年齡介于21到30之間。monogdb會使用索引的中的第一個鍵"age"得到匹配的結果,而結果通常是按照索引順序排列的。

db.users.find({'age': {"$gte": 21, "$lte": 30}}).sort({'username': 1})

與上一個類似,這次需要對結果排序。
在沒有sort時,我們查詢的結果首先是根據age等于21,age等于22..這樣從小到大排序,當age等于21有多個時,在進行usernameA-Z(0-9)這樣排序。所以,sort({'username': 1}),要將所有結果通過名字升序排列,這次不得不先在內存中進行排序,然后返回。效率不如上一個高。

當然,在文檔非常少的情況,排序也花費不了多少時間。
如果結果集很大,比如超過32MB,MongoDB會拒絕對如此多的數據進行排序工作。

還有另外一種解決方案

也可以建立另外一個索引{'username': 1, 'age': 1}, 如果先對username建立索引,當再sortusername,相當沒有進行排序。但是需要在整個文檔查找age等于21的帥哥美女,所以搜尋時間就長了。

但哪個效率更高呢?

如果建立多個索引,如何選擇使用哪個呢?
效率高低是分情況的,如果在沒有限制的情況下,不用進行排序但需要搜索整個集合時間會遠超過前者。但是在返回部分數據(比如limit(1000)),新的贏家就產生了。

>db.users.find({'age': {"$gte": 21, "$lte": 30}}).sort({username': 1}).limit(1000).hint({'age': 1, 'username': 1})explain()['millis']2031ms>db.users.find({'age': {"$gte": 21, "$lte": 30}}).sort({username': 1}).limit(1000).hint({'username': 1, 'age': 1}).explain()['millis']181ms

其中可以使用hint指定要使用的索引。
所以這種方式還是很有優勢的。比如一般場景下,我們不會把所有的數據都取出來,只是去查詢最近的,所以這種效率也會更高。

索引類型

唯一索引

可以確保集合的每個文檔的指定鍵都有唯一值。

db.users.ensureIndex({'username': 1, unique: true})
比如使用mongoose框架,在定義schema時,即可指定unique: true.
如果插入2個相同都叫張三的數據,第二次插入的則會失敗。_id即為唯一索引,并且不能刪除。

稀疏索引

使用sparse可以創建稀疏索引

>db.users.ensureIndex({'email': 1}, {'unique': true, 'sparse': true})

索引管理

system.indexes集合中包含了每個索引的詳細信息

db.system.indexes.find()

1.ensureIndex()創建索引

db.users.ensureIndex({'username': 1})
后臺創建索引,這樣數據庫再創建索引的同時,仍然能夠處理讀寫請求,可以指定background選項。

db.test.ensureIndex({"username":1},{"background":true})

2.getIndexes()查看索引

db.collectionName.getIndexes()db.users.getIndexes()[  {    "v" : 1,    "key" : {      "_id" : 1    },    "ns" : "test.users",    "name" : "_id_"  },  {    "v" : 1,    "key" : {      "username" : 1    },    "ns" : "test.users",    "name" : "username_1"  }]

其中v字段只在內部使用,用于標識索引版本。

3.dropIndex刪除索引

> db.users.dropIndex("username_1"){ "nIndexesWas" : 2, "ok" : 1 }

全選復制放進筆記> db.users.dropIndex({"username":1})



注:相關教程知識閱讀請移步到MongoDB頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕亚洲自拍| 在线性视频日韩欧美| 亚洲精品720p| 日韩欧美一区二区三区| 日韩国产一区三区| 国产日韩精品在线| 亚洲国产99精品国自产| 国产一区二区三区视频免费| 成人自拍性视频| 97视频在线观看免费| 久久97精品久久久久久久不卡| 97色在线视频观看| 欧美日本黄视频| 亚洲www在线| 欧美性做爰毛片| 欧美国产精品人人做人人爱| 高清日韩电视剧大全免费播放在线观看| 在线观看不卡av| 久久免费成人精品视频| 成人精品一区二区三区电影黑人| 91久久精品美女| 国产精品主播视频| 欧美亚洲激情视频| 欧美亚洲在线观看| 国产精品亚洲网站| 亚洲色图国产精品| 97精品在线视频| 欧美国产精品人人做人人爱| 欧美性在线观看| 日韩精品视频在线免费观看| 热草久综合在线| 国产成人91久久精品| 尤物精品国产第一福利三区| 国产性色av一区二区| 亚洲国产精品字幕| 欧美日韩福利在线观看| 日本成人黄色片| 精品毛片三在线观看| 日韩av一区二区在线观看| 91久久久久久久久久| 成人免费观看49www在线观看| 欧美日韩国产综合新一区| 亚洲美女av黄| 国产999精品久久久影片官网| 欧美成人激情视频免费观看| 国产亚洲精品va在线观看| 国产成人高清激情视频在线观看| 亚洲国产精品人久久电影| 中文字幕一区二区三区电影| 大量国产精品视频| 国产日韩欧美中文在线播放| 美乳少妇欧美精品| 亚洲色图av在线| 欧美日韩在线免费| 国产欧美亚洲视频| 国产日韩一区在线| 亚洲第一福利视频| 亚洲欧美精品中文字幕在线| 国产精品国产三级国产aⅴ浪潮| 久久精品91久久香蕉加勒比| 亚洲高清免费观看高清完整版| 亚洲福利在线看| 久久久亚洲网站| 国产亚洲精品一区二555| 亚洲欧美激情视频| 成人黄色生活片| 亚洲欧美日韩精品久久亚洲区| 亚洲成色777777女色窝| 国内精品久久久久| 尤物九九久久国产精品的分类| 国产精品精品视频一区二区三区| 亚洲第一免费播放区| 色偷偷888欧美精品久久久| 色偷偷888欧美精品久久久| 一本色道久久88亚洲综合88| 国产91成人video| 4388成人网| 日韩高清人体午夜| 亚洲国产天堂久久综合网| 成人性生交大片免费看视频直播| 亚洲电影免费观看高清完整版| 91成品人片a无限观看| 亚洲sss综合天堂久久| 亚洲一区二区中文| 国产精品成人va在线观看| 国产精品入口福利| 亚洲风情亚aⅴ在线发布| 亚洲欧美国内爽妇网| 九九久久久久久久久激情| 人体精品一二三区| 国产成人福利网站| 视频在线观看99| 国产精品美女视频网站| 国产精品欧美亚洲777777| 国产午夜精品美女视频明星a级| 久久99精品久久久久久噜噜| 日韩中文字幕av| 亚洲高清免费观看高清完整版| 伊人久久五月天| 欧美电影在线观看高清| 亚洲午夜未满十八勿入免费观看全集| 狠狠躁夜夜躁久久躁别揉| 久久亚洲一区二区三区四区五区高| 欧美电影《睫毛膏》| 亚洲男人天堂古典| 欧美亚洲另类激情另类| 久久男人的天堂| 91网在线免费观看| 亚洲精品v天堂中文字幕| 热99精品只有里视频精品| 国产精品99免视看9| 91九色蝌蚪国产| 91亚洲精品在线观看| 久精品免费视频| 成人精品视频久久久久| 国产午夜精品全部视频播放| 日本久久精品视频| 亚洲精品一区久久久久久| 一区二区三区视频观看| 国产亚洲福利一区| 国产精品综合久久久| 精品av在线播放| 欧美性猛交xxxx乱大交极品| 亚洲精品成a人在线观看| www.午夜精品| 日韩在线视频播放| 欧美精品成人91久久久久久久| 中日韩美女免费视频网址在线观看| 亚洲色图在线观看| 成人国产精品免费视频| 不卡伊人av在线播放| 国产日韩在线亚洲字幕中文| www.亚洲一二| 亚洲色图17p| 欧美中文字幕在线播放| 精品久久久久久中文字幕大豆网| 最好看的2019年中文视频| 午夜精品国产精品大乳美女| 2019亚洲日韩新视频| 91久久在线视频| 日韩精品免费一线在线观看| 日本sm极度另类视频| 日本久久91av| 欧美日韩亚洲精品一区二区三区| 亚洲人成在线一二| 国产网站欧美日韩免费精品在线观看| 久久久久久久999精品视频| 成人黄色免费网站在线观看| 欧美黑人国产人伦爽爽爽| 亚洲伊人成综合成人网| 成人亚洲欧美一区二区三区| 亚洲最大av在线| 国产欧美日韩免费看aⅴ视频| 91禁外国网站| 欧美精品在线免费观看| 久久久亚洲精品视频| 国产精品偷伦一区二区| 亚洲最大的网站| 456国产精品| 红桃视频成人在线观看| 久久影院中文字幕| 日本成人免费在线| 久久久久久久久久婷婷| 97人人做人人爱|