MongoDB 基礎(三)mongodb 中的索引使用,mongodb索引

來源:互聯網
上載者:User

MongoDB 基礎(三)mongodb 中的索引使用,mongodb索引

MongoDB中的索引和其他資料庫索引類似,也是使用B-Tree結構。MongoDB的索引是在collection層級上的,並且支援在任何列或者集合內的文檔的子列中建立索引。

 

下面是官方給出的一個使用索引查詢和排序的一個結構圖。


所有的MongoDB集合預設都有一個唯一索引在欄位“_id”上,如果應用程式沒有為 “_id”列定義一個值,MongoDB將建立一個帶有ObjectId值的列。(ObjectId是基於 時間、電腦ID、進程ID、本地進程計數器 產生的)


MongoDB 同樣支援在一列或多列上建立升序或降序索引。

MongoDB還可以建立 多鍵索引、數組索引、空間索引、text索引、雜湊索引,其屬性可以是唯一性索引、稀疏性索引、TTL(time to live)索引。

 

索引的限制:

索引名稱不能超過128個字元

每個集合不能超過64個索引

複合索引不能超過31列


MongoDB 索引文法

db.collection.createIndex({ <field>: < 1 or -1 > })

db.collection.ensureIndex({ <field>: < 1 or -1 > })

 

db.collection.createIndex( { "filed": sort } )

db.collection.createIndex( { "filed": sort , "filed2": sort } )

 

db.tab.ensureIndex({"id":1})

db.tab.ensureIndex({"id":1} ,{ name:"id_ind"})

db.tab.ensureIndex({"id":1,"name":1},{background:1,unique:1})

db.tab.ensureIndex( { "id" : "hashed" })

 

建立索引(兩種方法)

 

 

filed :為鍵列

sort :為排序。1 為升序;-1為降序。

 

建立單列索引

建立索引並給定索引名稱

後台建立唯一的複合索引

建立雜湊索引

 (更多參數 看文章底部)

db.tab.indexStats( { index: "id_ind" } )

db.runCommand( { indexStats: "tab", index: "id_ind" } )

db.tab.getIndexes()

db.system.indexes.find()

(前2個似乎不能用,官方文檔解釋)

(not intended for production deployments)

查看索引

db.tab.totalIndexSize();

查看索引大小

db.tab.reIndex()

db.runCommand({reIndex:"tab"})

重建索引

db.tab.dropIndex(<indexname>)

db.tab.dropIndex("id_1")

db.tab.dropIndexes()

刪除索引

<indexname>為getIndexes看到的索引名稱

刪除所有索引(注意!)

 

 



索引效能測試:

 

查看索引是否生效,分析查詢效能有沒有提高。先插入10萬資料到集合tab

 

for(var i=0;1<=100000;i++){

var value=parseInt(i*Math.random());

db.tab.insert({"id":i,"name":"kk"+i,"value":value});

}

 

不知道是不是虛擬機器的原因,插入了10分鐘都未完成!~

自己又開啟檔案夾查看,一直進不去檔案夾。結果用戶端串連斷開了!~查看服務竟然停了!



重啟服務,進去查看行數:96萬!(過後再查看吧!就用這資料測試了!)

db.tab.find().count()


AnalyzeQuery Performance :http://docs.mongodb.org/manual/tutorial/analyze-query-plan/

分析函數

db.tab.find({"name":"kk50000"}).explain()

查詢name=”kk50000”的執行分析

db.tab.find({"name":"kk50000"}).explain("queryPlanner")

db.tab.find({"name":"kk50000"}).explain("Verbosity")

db.tab.find({"name":"kk50000"}).explain("executionStats")

db.tab.find({"name":"kk50000"}).explain("allPlansExecution")

這3種方法執行結果完全包括上面這種的結果

db.tab.find({"name":"kk50000"}).explain()  結果做分析:

"cursor" : "BasicCursor",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 966423,

"nscanned" : 966423,

"nscannedObjectsAllPlans" : 966423,

"nscannedAllPlans" : 966423,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 7555,

"nChunkSkips" : 0,

"millis" : 4677,

"server" : "kk-ad:27017",

"filterSet" : false

遊標類型。BasicCurso(掃描), BtreeCursor(索引)

是否多鍵(組合)索引

返回行數

掃描行數

掃描行數

所有計劃掃描的次數

所有計劃掃描的次數

是否在記憶體中排序

 

 

 

耗時(毫秒)

伺服器

 



現在建立索引:

db.tab.createIndex({"name":1})



db.tab.find({"name":"kk50000"}).explain() 使用索引的結果

"cursor" : "BtreeCursor name_1",

 "isMultiKey" : false,

 "n" : 1,

 "nscannedObjects" : 1,

 "nscanned" : 1,

 "nscannedObjectsAllPlans" : 1,

 "nscannedAllPlans" : 1,

 "scanAndOrder" : false,

 "indexOnly" : false,

 "nYields" : 0,

 "nChunkSkips" : 0,

 "millis" : 1,

 "indexBounds" : {

         "name" : [

                 [

                         "kk50000",

                         "kk50000"

                 ]

         ]

 },

 "server" : "kk-ad:27017",

 "filterSet" : false

遊標使用索引BtreeCursor = name_1

 

 

 

 

 

 

 

 

 

 

耗時:1毫秒

 

 

 

 

 

 

 

 

 

 


上面可以看到,沒使用索引時,耗時4677毫秒,使用索引後,1毫秒!~並且不用全文檔掃描。



索引提示(hint),當前collection建立的索引:

db.tab.ensureIndex({"id":1} ,{name:"id_ind"})

db.tab.ensureIndex({"id":1,"name":1},{background:1,unique:1})

db.tab.ensureIndex( { "name" :"hashed" })


現在查詢 id=5000 的行(結果集為1行)

db.tab.find({"id": 5000}).explain()



查詢使用的是id和name的複合索引。

"nscannedObjectsAllPlans" : 2,

 "nscannedAllPlans" : 2,

 

現在加上索引提示,強制使用索引:

db.tab.find({"id": 5000}).hint({"id":1}).explain()



這時使用的是單個鍵列為id的索引。

"nscannedObjectsAllPlans" : 1,

"nscannedAllPlans" : 1,

 

上面還可以看到,索引有個邊界值“indexBounds”



這個邊界值在複合索引查詢的時候,會導致掃描更多的資料。這是一個bug :wrong index ranges when using compound index on a list


當然我們也可以自己限制邊界值。

db.tab.find().min({"id":5000}).max({ "id":5005})



從上面看,實際只查詢這個邊界的內的數值。再查看執行計畫:

db.tab.find().min({"id":5000}).max({ "id":5005}).explain()



只是5行資料。如果查詢id=5000的,但是索引邊界又有問題,這時可以限制邊界,如:

db.tab.find({"id": 5000 }).min({"id":5000}).max({ "id":5005})



在索引方法中,還有一個方法為cursor.snapshot(),它會確保查詢不會多次返回相同的文檔,即使是寫操作在一個因為文檔大小增長而移動的文檔。但是,snapshot()不能保證插入或者刪除的隔離性。snapshot()是使用在_id鍵列上的索引,因此snapshot()不能使用sort() 或 hint()。


分快照函數析snapshot()的查詢結果:

db.tab.find({"id": 5000}).snapshot().explain()


雖然使用了索引“_id”,但是把整個集合都搜尋了!~

 

加索引提示看看,應該是報錯的:

db.tab.find({"id": 5000}).snapshot().hint({"id":1})


果然是出錯:snapshot 不能使用提示。



下面總結索引查詢的一些方法:

Indexing Query Modifiers

db.tab.find({"id": 5000 }).hint({"id":1})

db.tab.find({"id": 5000 })._addSpecial("$hint",{"id":1})

db.tab.find({ $query: {"id": 5000 }, $hint: { "id":1 }})

使用鍵列id的索引查詢id=5000的結果

db.tab.find({"id": 5000 }).snapshot()

db.tab.find({"id": 5000 })._addSpecial( "$snapshot", true )

db.tab.find({ $query: {"id": 5000 }, $snapshot: true })

使用快照的查詢id=5000的結果

db.tab.find({"id": 5000 }).hint({"id":1}).explain()

db.tab.find({"id": 5000})._addSpecial("$explain",1)

db.tab.find({ $query: {"id": 5000 }, $hint: { "id":1 }, $explain: 1})

查看執行計畫資訊

索引邊界設定

db.tab.find({"id": 5000 }).max({ "id":5005})

db.tab.find({ $query:{"id": 5000 },$max:{ "id": 5005}})

db.tab.find({"id": 5000 })._addSpecial("$max",{"id": 5005})

 

db.tab.find({"id": 5000 }).min({ "id":5000}).max({ "id":5005}).explain()

db.tab.find({ $query:{"id": 5000 },$max:{ "id": 5005},$min:{ "id": 5000}})

db.tab.find({"id": 5000 })._addSpecial("$min",{"id": 5000})._addSpecial("$max",{"id": 5005})



摘取了這了的一個總結:http://www.w3cschool.cc/mongodb/mongodb-indexing.html

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.



更多參考官方文檔:Indexes


相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.