在MongoDB中通過建立索引可以進行高效的查詢芍耘,如果沒有索引MongoDB將會掃描整個集合與查詢的條件進行匹配蒋纬,這對于性能會造成很大的消耗臀蛛。
技術博客: Node.js技術棧
快速導航
面試指南
-
生產環(huán)境如何正確創(chuàng)建索引?
吓笙,參考:#
Mongodb索引類型
MongoDB提供了不同的索引類型支持在不同的業(yè)務場景進行查詢
1. _id索引
絕大多數集合默認建立索引己儒,對于每個插入的數據崎岂,MongoDB都會生成一條唯一的_id字段。
例如新創(chuàng)建一個集合時
db.demo_admin2.insert({x:1})
db.demo_admin2.getIndexes() # 查看集合索引闪湾,可看到_id索引
2. 單鍵索引
是最普通的索引冲甘,單鍵索引不會自動創(chuàng)建
例如一條記錄形式為:{x:1,y:2,z:3},只要在x字段上建立索引之后途样,就可以用x為條件進行查詢
db.demo_admin2.ensureIndex({x:1}) # 創(chuàng)建索引
db.demo_admin2.find({x:1}); # 使用索引查詢
3. 多鍵索引
多鍵索引與單鍵索引區(qū)別在于多鍵索引的值具有多個記錄江醇,是一個數組
db.demo_admin2.insert({x:[1,2,3,4]})
4. 復合索引
當查詢條件為多個時,需要建立復合索引
插入記錄{'x':1,'y':2,'z':3}
db.demo_admin2.insert({'x':1,'y':2,'z':3});
創(chuàng)建索引
db.demo_3.ensureIndex({x:1,y:1}) # 1升序何暇,-1降序
使用{x:1,y:1}
作為條件進行查詢
db.demo_admin2.find({x:1,y:2})
5. 過期索引
指在一段時間后會過期的索引陶夜,此索引過一段時間會過期,索引過期后裆站,相應的數據會被刪除条辟,適合存儲一些在一段時間之后會失效的數據,比如用戶登錄信息宏胯,這樣就不需要用到session了羽嫡。
5.1 創(chuàng)建過期索引
建立索引的時候需要多用一個參數,指定索引的有效時間——expireAfterSeconds肩袍,單位為秒
如下示例為time
字段創(chuàng)建過期索引
db.demo_3.ensureIndex({time:1},{expireAfterSeconds:10})
5.2 過期索引限制
過期索引字段值必須是指定的時間類型厂僧,必須是ISODate或ISODate數組,不能使用時間戳了牛,否則不能被自動刪除颜屠。
如果指定了ISODate數組,則按照最小的時間進行刪除鹰祸。 過期索引不能是復合索引甫窟。
刪除時間不是精確的,刪除過程是由后臺程序每60s跑一次蛙婴,而且刪除也需要一些時間粗井,所以存在誤差。
db.demo_3.ensureIndex({time:1},{expireAfterSeconds:30}
db.demo_3.insert({time:new Date()});
6. 全文索引
在mongodb中每個集合只允許創(chuàng)建一個索引,因此不用擔心存在多個索引造成沖突的問題浇衬。
6.1 全文索引創(chuàng)建
全文索引創(chuàng)建方法與創(chuàng)建單鍵索引懒构、復合索引類似。value換成'text'耘擂,$**匹配集合下所有
為一個字段創(chuàng)建全文索引
db.articles.ensureIndex({key:"text"})
為多個字段創(chuàng)建全文索引
db.articles.ensureIndex({key_1:"text"},{key_2:"text"})
為集合中所有的字段創(chuàng)建全文索引
db.articles.ensureIndex({"$**":"text"})
6.2 實例
建立索引
db.article.ensureIndex({"article":"text"})
db.articles.find({$text:{$search:"coffee"}})
db.articles.find({$text:{$search:"aa bb cc"}}) # 包含aa或bb或cc的數據
db.articles.find({$text:{$search:"aa bb -cc"}}) # 同時包含aa胆剧、bb且不包含cc的數據
db.articles.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}})# 同時包含aa、bb醉冤、cc的數據(用""包裹起來秩霍,引號需要用反斜杠\轉義)
6.3 mongodb相似度查詢
$meta
操作符:{score:{$meta:'textScore'}}
查詢結果的相似度,搜索出的結果會多出一個score字段蚁阳,這個得分越高铃绒,相關度越高。
db.article.find({$text:{$search:"aa bb ff"}},{score:{$meta:"textScore"}})
加上.sort方法可排序
db.article.find({$text:{$search:"aa bb ff"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
6.4 全局索引的限制
- 每次查詢螺捐,只能指定一個
$text
查詢 -
$text
查詢不能出現在$nor
查詢中 - 查詢中如果包含了
$text
,hint
不再起作用 - MongoDB全文索引還不支持中文
7.地理位置索引
- 2d索引颠悬,用于存儲和查找平面上的點
- 2dsphere索引,用于存儲和查找球面上的點
索引屬性
1.索引屬性name
MongoDB會自動的創(chuàng)建定血,規(guī)則是key_1 或者 key_-1 1或者-1代表排序方向椿疗,一般影響不大,長度一般有限制125字節(jié)
db.collection.ensureIndex({indexValue},{name: key})
為了見名知意我們可以自己來命名
db.demo_3.ensureIndex({x:1,y:1,z:1,n:1},{name:'xyz-name'});
刪除索引
db.demo_3.dropIndex(indexName)
2. 索引屬性unique唯一性指定
類似關系型數據庫字段的唯一約束
db.demo_3.ensureIndex({m:1,n:1},{unique:true})
索引實例測試
建立500萬條數據糠悼,分別用來測試建立索引和未建立索引的差別,只有在大量數據下才有效果浅乔,以下的示例中的時間消耗值倔喂,各電腦配置的不同在不同電腦上測試也會有不同的差別。
- 建立測試數據
> for(var i=0; i<5000000; i++) db.demo_user.insert({id: i})
WriteResult({ "nInserted" : 1 })
- 未建立索引情況數據查詢
在未建立索引的情況下靖苇,執(zhí)行數據查詢的時間消耗在6秒多席噩。
- 建立索引情況查詢數據
db.getCollection('demo_user').ensureIndex({"id": 1}) # 建立索引
下圖為建立索引的情況,在數據查詢中僅用了0.001秒贤壁,可見建立索引的重要的性悼枢。
索引導致的庫級鎖
這是一個很坑爹的事情,MongoDB沒有像MySql脾拆、Oracle擁有行級粒度鎖概念馒索,在MongoDB中只有庫級粒度鎖概念,意味這當你在生產環(huán)境中不小心觸發(fā)了一個寫鎖的操作時其它的業(yè)務也會受影響名船。
MongoDB中建立索引就是一個觸發(fā)寫鎖的過程绰上,通常數據量越大建立的索引占用的寫鎖時間就會越長,MongoDB中建立索引的兩種方式渠驼。
- 前臺創(chuàng)建(錯誤)
以下為前臺建立索引演示可以看到在執(zhí)行創(chuàng)建索引命令之后蜈块,新打開一個終端查詢另一張表一直處于等待狀態(tài),直到創(chuàng)建索引完成才返回數據。
db.getCollection('demo_user').ensureIndex({"id": 1}) # 建立索引
-
后臺創(chuàng)建(推薦)
基于后臺創(chuàng)建索引的方式在執(zhí)行創(chuàng)建索引命令之后百揭,新開一個終端查詢另一個集合中的數據可以立即得到返回爽哎。
db.getCollection('demo_user').ensureIndex({"id": 1}, {background: 1}) # 建立索引
作者:五月君
鏈接:https://www.imooc.com/article/285899
來源:慕課網
Github: Node.js技術棧