Mongodb索引探索(一)

索引是數(shù)據(jù)庫(kù)中的一個(gè)重要對(duì)象昧廷,主要用于支持高效查詢操作。如果沒有索引葵擎,數(shù)據(jù)庫(kù)就只能進(jìn)行全表掃描谅阿,效率將極為低下。mongodb的索引體系比較龐大酬滤,按照索引類型签餐,我準(zhǔn)備分這么幾個(gè)部分來進(jìn)行闡述:

  • 基本索引

  • Text索引

  • GEO索引

概述

本文將簡(jiǎn)單介紹常用的基本索引類型,已經(jīng)索引的相關(guān)操作盯串。根據(jù)官方的文檔氯檐,Mongodb有這么幾種常見索引:

  • Default _id 主鍵索引,默認(rèn)作用在_id

  • Single Field 單鍵索引体捏,針對(duì)單個(gè)field的索引

  • Compound 復(fù)合索引冠摄,針對(duì)多個(gè)field的索引

  • Multikey Index,這個(gè)我都不知道怎么翻几缭,多鍵索引吧河泳,其實(shí)就是針對(duì)數(shù)組子項(xiàng)的索引,因?yàn)閿?shù)組有多個(gè)元素年栓,每個(gè)元素都可能的key,如果有一個(gè)索引A作用在這個(gè)key上拆挥,這就是所謂的Multikey index

  • Geospatial Index 針對(duì)地理位置信息的索引

  • Text Index 支持全文搜索的索引,2.4才支持

  • Hashed Index 某抓, To support hash based sharding, MongoDB provides a hashed index (page 22) type, which indexes the hash of the value of a field.

同時(shí)纸兔,mongodb提供了兩個(gè)索引的屬性:

  • Unique 唯一性,保證索引作用的field上的value是唯一的否副。

  • Sparse 稀疏性汉矿,如果一個(gè)Collection中的某個(gè)field A 只存在于某些Document上,而 A 上同時(shí)建立了索引备禀,那么用Sparse則會(huì)使查詢操作直接忽略這些記錄洲拇。

好了,概念說了很多曲尸,來講一下索引的具體操作吧呻待。創(chuàng)建一個(gè)索引很簡(jiǎn)單,看看下面這些代碼:


// 單鍵索引
db.Student.ensureIndex({code:1});

// 復(fù)合索引
db.Student.ensureIndex({name:1,time:-1})

// Multikey Index
db.Student.ensureIndex({faver.id:1});

//  唯一索引
db.Student.ensureIndex({code:1},{unique:1});

// 唯一索引同時(shí)刪除重復(fù)值
db.Student.ensureIndex({code:1},{unique:1,dropDups:1});

// 唯一稀疏索引
db.Student.ensureIndex({code:1},{unique:1,sparse:1});


獲取一個(gè)Collection上面的集合信息

// 單個(gè)Collection
db.Student.getIndexes();

// DB中所有的Index
db.system.indexes.find();

刪除索引

// 刪除在某個(gè)field上面的索引
db.Student.dropIndex({name:1});

// 根據(jù)索引名刪除
db.system.indexes.remove({name:"code_-1"})

如何修改索引呢队腐?沒有特定修改命令,一般是先刪除奏篙,然后創(chuàng)建新的索引柴淘。

系統(tǒng)運(yùn)行一段時(shí)間以后迫淹,隨著數(shù)據(jù)的累加,業(yè)務(wù)需求的變化为严,可能會(huì)需要對(duì)索引進(jìn)行重建(rebuild)敛熬,則可以做這個(gè)操作:

db.collection.reIndex()

rebuild會(huì)先刪除集合上的所有索引,包括_id索引第股,然后重建应民。這種操作往往和耗時(shí),最好在系統(tǒng)資源充足的時(shí)候做夕吻。

細(xì)節(jié)

1. 限制

mongodb對(duì)索引的使用和管理也有一些限制

  • 索引key的總?cè)萘坎荒艽笥?024byte,否則以后的索引將創(chuàng)建不了

  • 單個(gè)集合不能超過64個(gè)索引

  • 單個(gè)索引的名字長(zhǎng)度(包括命名空間)不能超過125 個(gè)字符

  • 復(fù)合索引最多只能作用在31個(gè)field上

  • 一個(gè)查詢不能同時(shí)使用text and Geospatial 索引

上面列的只是一些大的限制诲锹,在具體場(chǎng)景中還有很多索引相互沖突,或者使用不當(dāng)造成索引無法命中的情況涉馅,所以還要看看更細(xì)節(jié)的一些東西归园。

2. 使用策略

2.1 _id 主鍵索引

這個(gè)是系統(tǒng)自動(dòng)創(chuàng)建的,不能刪除稚矿,除非你Drop掉整個(gè)Collection庸诱。這個(gè)效率是非常高的,對(duì)于一些數(shù)據(jù)量很大晤揣,但是沒有排序需求的集合(如日志表)桥爽,在分頁策略上應(yīng)該使用_id來進(jìn)行分頁。

2.2 single 單鍵索引

mongodb 不限制你在任何field上面創(chuàng)建單鍵索引昧识,但是一個(gè)查詢一次只能使用一個(gè)索引($or子句可以使用多個(gè))钠四,所以看看下面的情況會(huì)是這樣的:

//存在兩個(gè)索引:
{code:1},
{name:1}

//這里mongodb只會(huì)命中一個(gè)索引滞诺,具體是哪個(gè)由查詢分析器決定
db.Student.find({code:{$lt:10},name:{$regex:/^a/}}).explain();
{
    "cursor" : "BtreeCursor name_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 4,
    "nscannedAllPlans" : 4,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 46,
    "indexBounds" : {
        "name" : [
            [
                "a",
                "b"
            ]
        ]
    },
    "server" : "pormatoMacBook-Pro.local:27017"
}

索引還存在排序問題形导,{a:1}升序 / {a:-1}降序,但是對(duì)于單鍵索引习霹,排序的時(shí)候升序降序都會(huì)命中朵耕。如:

db.Student.find().sort({name:1});
db.Student.find().sort({name:-1});

2.3 復(fù)合索引

多數(shù)情況下,應(yīng)該考慮復(fù)合索引而非單鍵索引淋叶,因?yàn)閺?fù)合索引會(huì)包含部分單鍵索引阎曹。例如:
對(duì)于索引:
{a:1,b:1,c:1}
相當(dāng)于該集合擁有了:
{a:1} , {a:1,b:1} , {a:1,b:1,c:1}
但是:
{b:1} ,{c:1} , {b:1,c:1} 是無法命中的。

如果排序也希望命中索引的話煞檩,這里分為兩種情況:

  • 排序字段以索引開始鍵開頭
// 因?yàn)椴樵儣l件中不存在索引開始鍵(a:1)处嫌,要想命中索引,排序必須以索引開始鍵開頭
db.mycoll.find({b:{$gt:1}}).sort({a:1,b:1,c:1});
  • 排序字段不以索引開始鍵開頭
db.mycoll.find({a:{$gt:1}}).sort({b:1,c:1});

當(dāng)然斟湃,排序里面還有更為細(xì)致的問題熏迹,就是查詢條件如果有索引field的精準(zhǔn)匹配(equal),則排序也能更簡(jiǎn)單:

db.mycoll.find({a:1}).sort({b:1});

同樣,復(fù)合索引也存在索引反序問題,這里和單鍵索引一樣凝赛,只有完全反序才能命中:
對(duì)于索引{a:1,b:-1}, {a:-1,b:1} 是可以命中的注暗,反過來也成立坛缕。但是:{a:1,b:1}或者{a:-1,b:-1}是無法命中索引的。

3 MultiKey Index 多鍵索引

多鍵索引是作用在 array field上的element中的某個(gè)field上的索引捆昏。這個(gè)沒有太多的特別之處赚楚,唯一要注意的是,如果一個(gè)索引是復(fù)合多鍵索引,那么這個(gè)索引的field中只能有一個(gè)array類型骗卜。例如:
{a:1,b:[{b1:1,b2:1}] 這個(gè)是Ok的宠页, {a:[a1:1,a2:1],b:[{b1:1,b2:1}] 這種索引則是非法的。

其它

mongdb中還存在一種Cover Index的說法寇仓。它發(fā)生在如下的情況中:

  • all the fields in the query are part of an index, and

  • all the fields returned in the results are in the same index.

代碼


db.mycoll.find({a:{$lt:100}},{a:1,_id:0}});

這個(gè)時(shí)候查詢條件的field和 查詢域field 完全一樣举户,并且這個(gè)field剛好能命中索引的話,這個(gè)查詢效率將非常的高焚刺,因?yàn)閙ongodb不會(huì)再去硬盤進(jìn)行掃描敛摘,而是直接將Index信息返回。

這里需要知道的是如果在下面兩種情況下乳愉,Cover Index將無法生效

  • any of the indexed fields in any of the documents in the collection includes an array. If an indexed field is an array, the index becomes a multi-key index , index and cannot support a covered query.
    數(shù)組field將直接會(huì)使索引變?yōu)槎噫I索引

  • any of the indexed fields are fields in subdocuments. To index fields in subdocuments, use dot notation.
    查詢域總是會(huì)返回整個(gè)子文檔的root節(jié)點(diǎn)

基本的索引類型就是這么多了兄淫,接下來還有Text , Geo ,hash等較為復(fù)雜的索引類型,這個(gè)在以后的文章中再來分析蔓姚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捕虽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子坡脐,更是在濱河造成了極大的恐慌泄私,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件备闲,死亡現(xiàn)場(chǎng)離奇詭異晌端,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恬砂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門咧纠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泻骤,你說我怎么就攤上這事漆羔。” “怎么了狱掂?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵演痒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我趋惨,道長(zhǎng)鸟顺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任器虾,我火速辦了婚禮诊沪,結(jié)果婚禮上养筒,老公的妹妹穿的比我還像新娘。我一直安慰自己端姚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布挤悉。 她就那樣靜靜地躺著渐裸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪装悲。 梳的紋絲不亂的頭發(fā)上昏鹃,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音诀诊,去河邊找鬼洞渤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛属瓣,可吹牛的內(nèi)容都是我干的载迄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼抡蛙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼护昧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起粗截,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤惋耙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后熊昌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绽榛,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年婿屹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灭美。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡选泻,死狀恐怖冲粤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情页眯,我是刑警寧澤梯捕,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站窝撵,受9級(jí)特大地震影響傀顾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碌奉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一短曾、第九天 我趴在偏房一處隱蔽的房頂上張望寒砖。 院中可真熱鬧,春花似錦嫉拐、人聲如沸哩都。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漠嵌。三九已至,卻和暖如春盖呼,著一層夾襖步出監(jiān)牢的瞬間儒鹿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工几晤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留约炎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓蟹瘾,卻偏偏與公主長(zhǎng)得像圾浅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子热芹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 索引能夠提高數(shù)據(jù)庫(kù)的查詢效率贱傀,沒有索引的話,查詢會(huì)進(jìn)行全表掃描(scan every document in...
    zhglance閱讀 2,022評(píng)論 0 6
  • 索引(index) 索引 index經(jīng)常用于常用的查詢伊脓,如果設(shè)計(jì)得好府寒,在創(chuàng)建索引之后的查詢會(huì)有提升效率的效果。但是...
    我看不見閱讀 3,256評(píng)論 0 6
  • Spark SQL, DataFrames and Datasets Guide Overview SQL Dat...
    草里有只羊閱讀 18,303評(píng)論 0 85
  • 早上六點(diǎn)报腔,杜塞爾多夫天還沒有亮株搔,六點(diǎn)五十五分的火車去阿姆斯特丹。昨晚查了地鐵這會(huì)還沒開纯蛾,想著大不了走去火車站纤房,但是...
    吳俐溫哪閱讀 908評(píng)論 0 1
  • 第一次感覺到“我有幾千萬里的山光想與你說,這沿途的星辰也想粒粒分明摘取下來交由你翻诉,你可不可以等我炮姨。” ?我對(duì)你的喜...
    ryyx閱讀 435評(píng)論 0 0