mongodb學習(三)-mongodb索引

3.mongodb索引

@(mongodb)

在數據量特別大(幾百萬)的情況下,如果沒有建立索引,那麼對於沒有建立索引的字段進行查詢將不會返回任何數據,因此建立索引是十分重要的

格式

db.COLLECTION_NAME.ensureIndex({KEY:1},{Parameter:value})
Parameter Type Description
background Boolean 建索引過程會阻塞其它數據庫操作,background可指定以後臺方式創建索引,即增加 “background” 可選參數。 “background” 默認值爲false。
unique Boolean 建立的索引是否唯一。指定爲true創建唯一索引。默認值爲false.
name string 索引的名稱。如果未指定,MongoDB的通過連接索引的字段名和排序順序生成一個索引名稱。
dropDups Boolean 在建立唯一索引時是否刪除重複記錄,指定 true 創建唯一索引。默認值爲 false.
sparse Boolean 對文檔中不存在的字段數據不啓用索引;這個參數需要特別注意,如果設置爲true的話,在索引字段中不會查詢出不包含對應字段的文檔.。默認值爲 false.
expireAfterSeconds integer 指定一個以秒爲單位的數值,完成 TTL設定,設定集合的生存時間。
v index version 索引的版本號。默認的索引版本取決於mongod創建索引時運行的版本。
weights document 索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引字段的得分權重。
default_language string 對於文本索引,該參數決定了停用詞及詞幹和詞器的規則的列表。 默認爲英語
language_override string 對於文本索引,該參數指定了包含在文檔中的字段名,語言覆蓋默認的language,默認值爲 language.

例子:db.values.ensureIndex({open: 1, close: 1}, {background: true})在後臺創建索引
db.collenction.ensureIndex({x:1,y:2,z:3},{name="normal_index"})//指定名字
db.collenction.dropIndex("normal_index") 可用名字代替刪除索引
db.collenction.ensureIndex(({m:1,n:1}, {unique: true/false})唯一索引,這裏注意,如果是已經有了記錄的表,可能會報錯“E11000 duplicate key error collection: test.collenctionindex: m_1_n_1 dup key: { : null, : null }”原因是在你建立m:1,n:1的複合索引時,之前存在的多筆數據都沒有m和n的字段,也就代表每一筆沒有m和n字段的數據都是索引m:null,n:null的情形,而此時你又指定該複合索引爲unique,立刻報索引重複錯誤!
db.collenction.ensureIndex({title : 1}, {sparse : true})稀疏索引,mongo的默認模式是密集索引,在稀疏索引的情況下,如果某個對象沒有索引的屬性,將不會建立一個{title:null}的索引,可加快插入的速度。和unique結合可以達成唯一插入,有則建索引,無則不建索引的效果,就不會出現上面提到的unique索引報錯的情況

基本操作

db.test_collection.getIndexes() //查看集合的索引情況
db.test_collection.ensureIndex({x:1}) //創建索引,key代表字段名,value值代表方向,1代表正向排序,-1 代表負向排序

如果數據量非常大,創建索引需要消耗一定的時間,創建索引的時候需要注意時機,如果已經有大量數據了,這個時候創建索引會嚴重影響數據庫的性能,
應該在創建數據表的時候就創建索引,索引是在插入數據之後創建的,所以,對插入數據有稍微的影響,不過對於提高的查詢效率而言是值得的

索引分類

_id索引

  • _id索引是絕大多數集合默認建立的 索引。
  • 對於每個插入的數據,MongoDB都會自動生成一條唯一的_id字段。

單鍵索引

單鍵索引是最普通的索引,單鍵索引不會自動創建
db.test_collection.ensureIndex({x:1}) //創建單鍵索引

多鍵索引

當爲一個字段插入的數據是一個數組(集合等表示多條數據就行)時,MongoDB爲對應的值,默認創建了一個多鍵索引
db.test_collections.insert({x:[1,2,3,4]})插入一個數組

> db.test_collections.find({x:4})
{ "_id" : ObjectId("5a44f99ca3fe201251392183"), "x" : [ 1, 2, 3, 4 ] }

直接就可以通過數組中的值查出來了

複合索引

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

過期索引

又稱 TTL(Time To Live,生存時間)索引,即在一段時間後會過期的索引(如登錄信息、日誌等)
過期後的索引會連同文檔一起刪除

  • 存儲在過期索引字段的值必須是指定的時間類型
    • 說明:必須是ISOData或者ISOData數組,不能使用時間戳
  • 如果指定的是ISOData數組,則按照數組中最小的數值計算刪除
  • 過期期索引不能是複合索引,只能是單鍵索引
  • 刪除時間不是精確
    • 說明:刪除過程是由後臺程序每60s跑一次,而且刪除也需要一些時間
db.local_2.ensureIndex({time:1},{expireAfterSeconds:30})
db.local_2.insert({time:new Date()})
db.local_2.find()

全文索引

全文索引建立

在MongoDB中每個數據集合只能創建一個全文索引, 所以使用全文索引進行查詢時不會起衝突

db.articles.ensureIndex({key:"text"})//單值索引的value是 1或者 -1代表正向或者你向,而全文索引的value則是固定的字符串”text”
db.articles.ensureIndex({key1:"text",key2:"text",key3:"text"})//多字段
db.articles.ensureIndex({"$**":"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的數據(用“”包裹起來,引號需要用反斜槓轉義)

全文索引的相似度

$meta操作符:{score:{$meta:"textScore"}}
寫在查詢條件之後可以返回返回結果的相似度,textScore爲固定字符串
與 sort 一起使用可以達到很好的使用效果

db.imooc_2.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}})
db.imooc_2.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}});根據score字段排序

實際查詢之後會見到如下所示的效果

> db.test_collection.find({$text:{$search:"aa"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})

{ "_id" : ObjectId("5a45f28022d4795f1452d9bf"), "article" : "aa", "score" : 1.1 }
{ "_id" : ObjectId("5a45f11522d4795f1452d9bb"), "article" : "aa bb cc dd", "score" : 0.625 }
{ "_id" : ObjectId("5a45f1a222d4795f1452d9bd"), "article" : "aa bb ii gg", "score" : 0.625 }
{ "_id" : ObjectId("5a45f1b422d4795f1452d9be"), "article" : "aa bb zz yy", "score" : 0.625 }
{ "_id" : ObjectId("5a45f19b22d4795f1452d9bc"), "article" : "aa bb cc ff hh", "score" : 0.6 }

全文索引的限制:

  • 每次查詢,只能指定一個$text查詢
  • $text查詢不能出現在$nor查詢中
  • 查詢中如果包含了$text, hint不再起作用
  • MongoDB全文索引在3.2版本之前還不支持中文

地理位置索引

概念:將一些點的位置存儲在MongoDB中,創建索引後,可以按照位置來查找其他點
子分類:
- 2d索引:用於存儲和查找平面上的點db.集合名.ensureIndex({w:"2d"})
- 2dsphere索引:用於存儲和查找球面上的點db.集合名.ensureIndex({w:"2dsphere"})

位置表示方式:經緯度[精度,緯度]
取值範圍:精度[-180,180],緯度[-90,90]。如果超出範圍會出現意想不到的錯誤
查找方法:
- 查找據李某個點一定距離內的點
- 查找包含在某區域內的點

2d索引

2d索引:db.集合名.ensureIndex({w:"2d"})

例子: db.集合名.find({w:{$near:[1,1]}})
db.collection.find({w:{$near:[1,1], $maxDistance:10}})查找距離[1,1]最大距離爲10的點,3.2版本後可以使用minDistance
db.collection.find({w:{$geoWithin:{$box:[[0,0],[3,3]]}}}) 查找在矩形[0,0] [3,3]範圍內的點
db.collection.find({w:{$geoWithin:{$center:[[0,0],5]}}}) 查找以[0,0]爲圓心半徑爲5的圓內的點
db.collection.find({w:{$geoWithin:{$polygon:[[0,0],[1,1],[4,5],[6,6]]}}}) 查找以[0,0],[1,1],[4,5],[6,6]爲多邊形內的點

想不明白的在腦子裏假想一個座標系,就很好理解了

geoNear查詢:

除了使用 find的方式之外,還可以使用runCommand來執行語句

db.runCommand({
geoNear:"集合名",
near:[x, y],
minDistance: (對2d索引無效)
maxDistance:
num:(返回的數量)
{
    "results":[     //查詢的結果
        {
        "dis":  //查找到的數據與所指定查找的數據之間的距離
        "obj":{}    //查找到的數據
        }
    ],
    "stats":{   //查詢的參數
        "nscanned": //掃描了哪些數據
        "objectsloaded":
        "avgDistance":      //平均距離
        "maxDistance":  //最大的距離
        "time":     //花費的時間
    },
    "ok":
}

2dsphere索引

2dsphere索引: db.集合名.ensureIndex({w:"2dsphere"})

2Dsphere位置表示方式:
GeoJSON:描述一個點,一條直線,多邊形等形狀。
格式:
{type:”, coordinates:[list]}
GeoJSON查詢可支持多邊形交叉點等,支持MaxDistance 和 MinDistance

詳細請看
基於MongoDB 2dSphere索引查找最近的點

索引分析

創建索引的好處:加快索引查詢。
創建索引的壞處:增加磁盤消耗,降低寫入性能。

索引分析的工具
- mongostat工具
- profile集合介紹
- 日誌
- explain分析

mongostat

mongostat是mongodb自帶的用來查看mongodb運行狀態的一個工具

使用方法:./mongostat -h ip:port -u -p

字段說明:

返回的採樣數據採用百分比

索引情況:idx miss 索引未命中率

輸出字段:

inserts –當前的插入數量(單位:秒)
query –當前的查詢數量(單位:秒)
update –當前更新的數量(單位:秒)
delete –當前的刪除數量(單位:秒)
getmore –當前的迭代返回數量(單位:秒)
command –執行命令的數量
flushes –刷盤時間(單位:秒)
mapped –mmap 大小
vsize –磁盤空間大小
res –常駐內存大小
faults –內存換頁時間(單位:秒)
locked –鎖的使用情況
idx miss –未命中索引率
qr|qw –讀|寫隊列
ar|aw –活躍的客戶端連接數量
netIn –網卡輸入流量
netOup –網卡輸出流量
conn –當前連接到mongodb的連接數量

inserts/query/update/delete: 分別指當前mongodb插入、查詢、更新、刪除 數量,以每秒計;
getmore: MongoDB返回結果時,每次只會返回一定量;當我們繼續用find()查詢更多數據時,系統就會自動用getmore來獲取之後的數據;
command: 執行的命令數量;
flushes: MongoDB使用虛擬內存映射的方式管理數據,我們在向MongoDB寫入或查詢數據時,MongoDB會做一次虛擬內存映射,有些數據其實是在硬盤上的;每隔一段時間,MongoDB會把我們寫到內存的數據flush到硬盤上;這個數據大的話,會導致mongodb的性能較差;
mapped/vsize/res: 與磁盤空間大小有關,申請的內存大小;
faults:如果我們查詢的數據,沒有提前被MongoDB加載到內存中,我們就必須到硬盤上讀取,叫做“換頁”;如果faults比較高,也會造成性能下降;
idx miss: 表示我們的查詢沒有命中索引的比率;如果很高,說明索引構建有問題,索引不合適或者索引數量不夠;
qr|qw: 說明MongoDB的寫隊列或者讀隊列的情況。我們向MongoDB讀寫時,這些請求會被放到隊列中等待。數量大(幾百上千)說明MongoDB處理速度慢或者讀寫請求太多,性能會下降。
ar|aw: 當前活躍的讀寫客戶端的個數。

qr/qw 表示讀隊列和寫隊列值,較高時數據庫的性能會很明顯的下降
idx miss 表示查詢時索引命中情況,較高時影響查詢效率

profile

db.getProfilingStatus()
{ “was” : 0, “slowms” : 100 }
查看當前數據庫的記錄級別

db.getProfilingLevel()
0|1|2
設置當前數據庫的profile記錄級別
db.setProfilingLevel(0|1|2)

was –profile記錄級別,0關閉,1記錄所有超過slowms閾值的慢查詢,2記錄所有操作
slowms –慢查詢閥值

查看profile文件
db.system.profile.find()
db.system.profile.find().sort({$natural:-1}).limit(1)查詢profile集合的內容,自然排序,限制只顯示一條日誌

{ "op" : "query",--操作類型
"ns" : "imooc.system.profile", --查詢的命名空間,;databasename.collectionname'
"query" : { "query" : { }, --查詢條件
"orderby" : { "$natural" : -1 } }, --約束條件
"ntoreturn" : 1, --返回數據條目
"ntoskip" : 0, --跳過的條目
"nscanned" : 1, --掃描的數目含索引
"nscannedObjects" : 1, --掃描的數據數目
"keyUpdates" : 0, --
"numYield" : 0, --其他情況
"lockStats" : { --鎖狀態
"timeLockedMicros" : { --鎖佔用時間(毫秒)
"r" : NumberLong(82), --讀鎖
"w" : NumberLong(0) --寫鎖
},
"timeAcquiringMicros" : {
"r" : NumberLong(2), "w" : NumberLong(2)
}
},
"nreturned" : 1,
"responseLength" : 651, --返回長度
"millis" : 0, --查詢時間

注意:如果開啓了profile的功能,並且此時profile記錄的數據比較大,系統的消耗是比較大的,所以,這個工具最好在上線之前的測試時開啓此功能,用來查看數據庫的設計和應用程序的設計,上線的系統是不建議使用此方法的,因爲系統的開銷比較大!

mongodb日誌

就是log目錄下的那個日誌

berbose = vvvvv 日誌記錄級別,1-5個v,越多越詳細

explain

db.colltction.find({x:1}).explain()

{
“cursor” : “BasicCursor”, –使用的遊標
“isMultiKey” : false,
“n” : 1,
“nscannedObjects” : 100000, –掃描的數據量
“nscanned” : 100000, –包含索引的掃描量
“nscannedObjectsAllPlans” : 100000,
“nscannedAllPlans” : 100000,
“scanAndOrder” : false,
“indexOnly” : false,
“nYields” : 781,
“nChunkSkips” : 0,
“millis” : 25, –查詢消耗時間(毫秒)
“server” : “XXX”,
“filterSet” : false
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章