Mongo索引學習筆記

索引使用場景

優:加快查詢速度javascript

劣:增刪改會產生額外的開銷、佔用空間html

tips: 返回集合中一半以上的數據,全表掃描的效率高java

索引基礎

基礎操做

查看索引:db.test.getIndexes()正則表達式

建立索引:db.test.ensureIndex({"username":1},{"background":true,"name":"index_test_name"}) //已有大量數據時可後臺執行不阻塞數組

刪除索引: db.test.dropIndex({"username":1})app

查看索引大小: db.test.totalIndexSize()函數

屬性

索引順序:性能

1爲正序,-1爲逆序優化

在複合索引中需注意順序(id:1, age:-1)ui

索引屬性:

惟一性

db.test.ensureIndex({x:1,y:1},{unique:true})

稀疏性

db.test.ensureIndexx({},{sparse:true/false})
不稀疏(默認):
1. 可插入不存在索引字段的數據,null; 
2. 可篩選不存在字段: db.test.find({m:{$exist:ture}})
稀疏:

優化分析方法

explain

獲知系統如何處理請求

cursor  返回遊標類型(BasicCursor或BtreeCursor)
nscanned  被掃描的文檔數量
n 返回的文檔數
millis  耗時(毫秒)
indexBounds  所使用的索引

hint

強制使用某個索引

db.test.find({"age":20}).hint({"name":1,"age":1}) // .hint(name_1_age_1)

profile

設置日誌級別,記錄慢查詢

Tips

  1. 查詢條件順序自動調整
  2. 能爲前綴式的正則表達式命中索引(/^z/)
  3. 對須要大量sort的鍵創建索引,避免所有數據加載到內存
  4. $ne、$nin 不會使用索引

索引種類

_id索引

默認生成惟一字段

單鍵索引

值爲一個單一的值

db.test.ensureIndex({x:1})

多鍵索引

值具備多個記錄,如數組、內嵌文檔

db.test.insert({x:[1,2,3,4]})

每個索引字段最多包含一個數組

Y: {_id:1, a:[1,2], b:1, category:"A array"} 與 {_id:2, a:1, b:[1,2], category:"B array"}
N: {_id:3, a:[1,2], b:[1,2], category:"AB both array"}

查詢

//數組查詢
數組中包含: db.fruitshop.find({"fruits":"apple"})
包含多個: db.fruitshop.find({"fruits":{"$all":["apple", "banana"]}})
精確匹配: db.fruitshop.find({"fruits":["apple","orange","pear"]}) //順序與數量一致
特定位置元素查詢: db.fruitshop.find({"fruits.1":"orange"})
查詢數組長度: db.fruitshop.find({"fruits":{"$size":3}}) //size不能和其餘操做符連用,如'$gt'等
返回固定長度: db.fruitshop.find({"fruits":{"$slice":2}}) //前2個
              db.fruitshop.find({"fruits":{"$slice":-1}}) //後1個
              db.fruitshop.find({"fruits":{"$slice":[3,6]}}) //第4~7個,無數據則返回[]

//內嵌文檔
徹底匹配: db.staff.find({"name":{"first":"joe","middle":"bush"}}) //順序與數量一致
鍵值對查詢: db.staff.find({"name.first":"joe","name.middle":"bush"}) //點表示法,在插入時鍵名不能包含點(約束)
多層內嵌: elemMatch  db.blogs.find({"comment":{"$elemMatch":{"author":"joe", "score":{"$gte":3}}}}) //內嵌文檔中匹配author和score條件
          where  db.fruitshop.find({"$where":function(){}}) //性能低,每一個文檔轉換成一個javascript對象放入函數執行

複合索引

多個條件,從左到右執行

{a:1,b:1,c:1} => {a:1},{a:1,b:1},{a:1,b:1,c:1}

db.test.ensureIndex({x:1,y:1})

過時索引

一段時間後過時,刪除相應數據(用戶的登陸信息、存儲的日誌)

db.test.ensureIndex({time:1},{expireAfterSeconds:30})

限制

字段類型必須是ISODate或者ISODate數組(數組中最小的時間)
不能是複合索引(不能指定兩個過時時間)
刪除時間不精確(後臺進程60s跑一次)

全文索引

字符串或者字符串數組可搜索

//創建索引
db.test.ensureIndex({title:"text"})
db.test.ensureIndex({key1:"text",key2:"text"}) //對多個字段建立全文索引
db.test.ensureIndex({$**:"text"}) //對全部字段建全文索引

//查找
不須要指定字段名稱: db.test.find({"$text":{"$search":"coffee"}}) //每一個數據集合只容許建立一個全文索引(可針對一個、多個、所有字段)
查找多個關鍵詞(空格表明 或 操做): db.test.find({"$text":{"$search":"aa bb cc"}})
指定不包含詞(-表明 非 操做): db.test.find({"$text":{"$search":"aa bb -cc"}})
與關係操做: db.test.find({"$text":{"$search":"\"aa\" \"bb\" \"cc\""}})
類似度查詢: db.test.find({"$text":{"$search":"aa bb"}},{"score:{"$meta":"textScore"}"}) //score字段得分越高,相關度越高
            db.test.find({"$text":{"$search":"aa bb"}},{"score":{"$meta":"textScore"}}).sort({"score":{"$meta":"textScore"}}) //score相關度排序
            
//限制
每次查詢只能指定一個$text
有了$text則hint(強制指定索引)不起做用
中文支持很差(企業版可支持)

地理位置索引

將點的位置存儲,能夠按位置查找其餘點

2D索引
用於存儲和查找平面上的點

db.test.ensureIndex({w:"2d"})

//使用經緯度表示
取值範圍 經度[-180,180] 緯度[-90,90]
db.test.insert({w:[180,90]})

//查詢
使用$near查詢距離某個點最近的點(默認返回100個)
    db.test.find({"$near":[x,y]})
    db.test.find({w:{"$near":[x,y],"$maxDistance":"z"}}) //限制返回的最遠距離
 
使用$geoWithin查詢某個形狀內的點
    矩形($box:[[x1,y1],[x2,y2]]) db.test.find({w:{"$geoWithin:{"$box":[[0,0],[3,3]]}}"}})
    圓形($center:[[x,y],r])  db.test.find({w:{"$geoWithin":{"$center":[0,0],5}}})
    多邊形($polygon:[[x1,y1],[x2,y2],..)  db.test.find({w:{"$geoWithin":{"$polygon":[[0,0],[0,1],[2,5],[6,1]]}}})
    
使用$geoNear查詢,返回最大距離和平均距離等數據

相關擴展:
《地理位置索引的實現原理》

2Dsphere索引
用於存儲和查找球面上的點

db.test.ensureIndex({key:"2dsphere"})
相關文章
相關標籤/搜索