摘要:復(fù)合唯一索引也可以創(chuàng)建復(fù)合的唯一索引。中的稀疏索引與關(guān)系型數(shù)據(jù)庫中的稀疏索引是完全不同的概念。但是這里不會(huì)指明索引是否是多鍵索引。上一篇文章指南使用和何時(shí)不應(yīng)該使用索引下一篇文章指南特殊的索引和集合固定集合索引全文本索引
上一篇文章:MongoDB指南---12、使用explain()和hint()、何時(shí)不應(yīng)該使用索引
下一篇文章:MongoDB指南---14、特殊的索引和集合:固定集合、TTL索引、全文本索引
創(chuàng)建索引時(shí)可以指定一些選項(xiàng),使用不同選項(xiàng)建立的索引會(huì)有不同的行為。接下來的小節(jié)會(huì)介紹常見的索引變種,更高級(jí)的索引類型和特殊選項(xiàng)會(huì)在下一章介紹。
唯一索引唯一索引可以確保集合的每一個(gè)文檔的指定鍵都有唯一值。例如,如果想保證同不文檔的"username"鍵擁有不同的值,創(chuàng)建一個(gè)唯一索引就好了:
> db.users.ensureIndex({"username" : 1}, {"unique" : true})
如果試圖向上面的集合中插入如下文檔:
> db.users.insert({username: "bob"}) > db.users.insert({username: "bob"}) E11000 duplicate key error index: test.users.$username_1 dup key: { : "bob" }
如果檢查這個(gè)集合,會(huì)發(fā)現(xiàn)只有第一個(gè)"bob"被保存進(jìn)來了。發(fā)現(xiàn)有重復(fù)的鍵時(shí)拋出異常會(huì)影響效率,所以可以使用唯一索引來應(yīng)對(duì)偶爾可能會(huì)出現(xiàn)的鍵重復(fù)問題,而不是在運(yùn)行時(shí)對(duì)重復(fù)的鍵進(jìn)行過濾。
有一個(gè)唯一索引可能你已經(jīng)比較熟悉了,就是"_id"索引,這個(gè)索引會(huì)在創(chuàng)建集合時(shí)自動(dòng)創(chuàng)建。這就是一個(gè)正常的唯一索引(但它不能被刪除,而其他唯一索引是可以刪除的)。
如果一個(gè)文檔沒有對(duì)應(yīng)的鍵,索引會(huì)將其作為null存儲(chǔ)。所以,如果對(duì)某個(gè)鍵建立了唯一索引,但插入了多個(gè)缺少該索引鍵的文檔,由于集合已經(jīng)存在一個(gè)該索引鍵的值為null的文檔而導(dǎo)致插入失敗。5.4.2節(jié)會(huì)詳細(xì)介紹相關(guān)內(nèi)容。
有些情況下,一個(gè)值可能無法被索引。索引儲(chǔ)桶(index bucket)的大小是有限制的,如果某個(gè)索引條目超出了它的限制,那么這個(gè)條目就不會(huì)包含在索引里。這樣會(huì)造成一些困惑,因?yàn)槭褂眠@個(gè)索引進(jìn)行查詢時(shí)會(huì)有一個(gè)文檔憑空消失不見了。所有的字段都必須小于1024字節(jié),才能包含到索引里。如果一個(gè)文檔的字段由于太大不能包含在索引里,MongoDB不會(huì)返回任何錯(cuò)誤或者警告。也就是說,超出8 KB大小的鍵不會(huì)受到唯一索引的約束:可以插入多個(gè)同樣的8 KB長的字符串。
1. 復(fù)合唯一索引也可以創(chuàng)建復(fù)合的唯一索引。創(chuàng)建復(fù)合唯一索引時(shí),單個(gè)鍵的值可以相同,但所有鍵的組合值必須是唯一的。
例如,如果有一個(gè){"username" : 1, "age" : 1}上的唯一索引,下面的插入是合法的:
db.users.insert({"username" : "bob"})2. 去除重復(fù)
db.users.insert({"username" : "bob", "age" : 23})
db.users.insert({"username" : "fred", "age" : 23})
然而,如果試圖再次插入這三個(gè)文檔中的任意一個(gè),都會(huì)導(dǎo)致鍵重復(fù)異常。
GirdFS是MongoDB中存儲(chǔ)大文件的標(biāo)準(zhǔn)方式(詳見6.5節(jié)),其中就用到了復(fù)合唯一索引。存儲(chǔ)文件內(nèi)容的集合有一個(gè){"files_id" : 1, "n" : 1}上的復(fù)合唯一索引,因此文檔的某一部分看起來可能會(huì)是下面這個(gè)樣子:
{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 1}
{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 2}
{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 3}
{"files_id" : ObjectId("4b23c3ca7525f35f94b60a2d"), "n" : 4}
注意,所有"files_id"的值都相同,但是"n"的值不同。
在已有的集合上創(chuàng)建唯一索引時(shí)可能會(huì)失敗,因?yàn)榧现锌赡芤呀?jīng)存在重復(fù)值了:
> db.users.ensureIndex({"age" : 1}, {"unique" : true}) E11000 duplicate key error index: test.users.$age_1 dup key: { : 12 }
通常需要先對(duì)已有的數(shù)據(jù)進(jìn)行處理(可以使用聚合框架),找出重復(fù)的數(shù)據(jù),想辦法處理。
在極少數(shù)情況下,可能希望直接刪除重復(fù)的值。創(chuàng)建索引時(shí)使用"dropDups"選項(xiàng),如果遇到重復(fù)的值,第一個(gè)會(huì)被保留,之后的重復(fù)文檔都會(huì)被刪除。
> db.people.ensureIndex({"username" : 1}, {"unique" : true, "dropDups" : true})
"dropDups"會(huì)強(qiáng)制性建立唯一索引,但是這個(gè)方式太粗暴了:你無法控制哪些文檔被保留哪些文檔被刪除(如果有文檔被刪除的話,MongoDB也不會(huì)給出提示說哪些文檔被刪除了)。對(duì)于比較重要的數(shù)據(jù),千萬不要使用"dropDups"。
稀疏索引前面的小節(jié)已經(jīng)講過,唯一索引會(huì)把null看做值,所以無法將多個(gè)缺少唯一索引中的鍵的文檔插入到集合中。然而,在有些情況下,你可能希望唯一索引只對(duì)包含相應(yīng)鍵的文檔生效。如果有一個(gè)可能存在也可能不存在的字段,但是當(dāng)它存在時(shí),它必須是唯一的,這時(shí)就可以將unique和sparse選項(xiàng)組合在一起使用。
MongoDB中的稀疏索引(sparse index)與關(guān)系型數(shù)據(jù)庫中的稀疏索引是完全不同的概念。基本上來說,MongoDB中的稀疏索引只是不需要將每個(gè)文檔都作為索引條目。
使用sparse選項(xiàng)就可以創(chuàng)建稀疏索引。例如,如果有一個(gè)可選的email地址字段,但是,如果提供了這個(gè)字段,那么它的值必須是唯一的:
> db.ensureIndex({"email" : 1}, {"unique" : true, "sparse" : true})
稀疏索引不必是唯一的。只要去掉unique選項(xiàng),就可以創(chuàng)建一個(gè)非唯一的稀疏索引。
根據(jù)是否使用稀疏索引,同一個(gè)查詢的返回結(jié)果可能會(huì)不同。假如有這樣一個(gè)集合,其中的大部分文檔都有一個(gè)"x"字段,但是有些沒有:
> db.foo.find() { "_id" : 0 } { "_id" : 1, "x" : 1 } { "_id" : 2, "x" : 2 } { "_id" : 3, "x" : 3 }
當(dāng)在"x"上執(zhí)行查詢時(shí),它會(huì)返回相匹配的文檔:
> db.foo.find({"x" : {"$ne" : 2}}) { "_id" : 0 } { "_id" : 1, "x" : 1 } { "_id" : 3, "x" : 3 }
如果在"x"上創(chuàng)建一個(gè)稀疏索引,"_id"為0的文檔就不會(huì)包含在索引中。如果再次在"x"上查詢,MongoDB就會(huì)使用這個(gè)稀疏索引,{"_id" : 0}的這個(gè)文檔就不會(huì)被返回了:
> db.foo.find({"x" : {"$ne" : 2}}) { "_id" : 1, "x" : 1 } { "_id" : 3, "x" : 3 }
如果需要得到那些不包含"x"字段的文檔,可以使用hint()強(qiáng)制進(jìn)行全表掃描。
索引管理如前面的小節(jié)所述,可以使用ensuerIndex函數(shù)創(chuàng)建新的索引。對(duì)于一個(gè)集合,每個(gè)索引只需要?jiǎng)?chuàng)建一次。如果重復(fù)創(chuàng)建相同的索引,是沒有任何作用的。
所有的數(shù)據(jù)庫索引信息都存儲(chǔ)在system.indexes集合中。這是一個(gè)保留集合,不能在其中插入或者刪除文檔。只能通過ensureIndex或者dropIndexes對(duì)其進(jìn)行操作。
創(chuàng)建一個(gè)索引之后,就可以在system.indexes中看到它的元信息。可以執(zhí)行db.collectionName.getIndexes()來查看給定集合上的所有索引信息:
> db.foo.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.foo", "name" : "_id_" }, { "v" : 1, "key" : { "y" : 1 }, "ns" : "test.foo", "name" : "y_1" }, { "v" : 1, "key" : { "x" : 1, "y" : 1 }, "ns" : "test.foo", "name" : "x_1_y_1" } ]
這里面最重要的字段是"key"和"name"。這里的鍵可以用在hint、max、min以及其他所有需要指定索引的地方。在這里,索引的順序很重要:{"x" : 1, "y" : 1}上的索引與{"y" : 1, "x" : 1}上的索引不同。對(duì)于很多的索引操作(比如dropIndex),這里的索引名稱都可以被當(dāng)作標(biāo)識(shí)符使用。但是這里不會(huì)指明索引是否是多鍵索引。
"v"字段只在內(nèi)部使用,用于標(biāo)識(shí)索引版本。如果你的索引不包含"v" : 1這樣的字段,說明你的索引是以一種效率比較低的舊方式存儲(chǔ)的。將MongoDB升級(jí)到至少2.0版本,刪除并重建這些索引,就可以把索引的存儲(chǔ)方式升級(jí)到新的格式了。
集合中的每一個(gè)索引都有一個(gè)名稱,用于唯一標(biāo)識(shí)這個(gè)索引,也可以用于服務(wù)器端來刪除或者操作索引。索引名稱的默認(rèn)形式是key name1_dir1_keyname2_dir2_..._keynameN_dirN,其中keynameX是索引的鍵,dirX是索引的方向(1或者-1)。如果索引中包含兩個(gè)以上的鍵,這種命名方式就顯得比較笨重了,好在可以在ensureIndex中指定索引的名稱:
> db.foo.ensureIndex({"a" : 1, "b" : 1, "c" : 1, ..., "z" : 1}, ... {"name" : "alphabet"})
索引名稱的長度是有限制的,所以新建復(fù)雜索引時(shí)可能需要自定義索引名稱。調(diào)用getLastError就可以知道索引是否成功創(chuàng)建,或者失敗的原因。
修改索引隨著應(yīng)用不斷增長變化,你會(huì)發(fā)現(xiàn)數(shù)據(jù)或者查詢已經(jīng)發(fā)生了改變,原來的索引也不那么好用了。這時(shí)可以使用dropIndex命令刪除不再需要的索引:
> db.people.dropIndex("x_1_y_1") { "nIndexesWas" : 3, "ok" : 1 }
用索引描述信息里"name"字段的值來指定需要?jiǎng)h除的索引。
新建索引是一件既費(fèi)時(shí)又浪費(fèi)資源的事情。默認(rèn)情況下,MongoDB會(huì)盡可能快地創(chuàng)建索引,阻塞所有對(duì)數(shù)據(jù)庫的讀請(qǐng)求和寫請(qǐng)求,一直到索引創(chuàng)建完成。如果希望數(shù)據(jù)庫在創(chuàng)建索引的同時(shí)仍然能夠處理讀寫請(qǐng)求,可以在創(chuàng)建索引時(shí)指定background選項(xiàng)。這樣在創(chuàng)建索引時(shí),如果有新的數(shù)據(jù)庫請(qǐng)求需要處理,創(chuàng)建索引的過程就會(huì)暫停一下,但是仍然會(huì)對(duì)應(yīng)用程序性能有比較大的影響。后臺(tái)創(chuàng)建索引比前臺(tái)創(chuàng)建索引慢得多。
在已有的文檔上創(chuàng)建索引會(huì)比新創(chuàng)建索引再插入文檔快一點(diǎn)。
上一篇文章:MongoDB指南---12、使用explain()和hint()、何時(shí)不應(yīng)該使用索引
下一篇文章:MongoDB指南---14、特殊的索引和集合:固定集合、TTL索引、全文本索引
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/44098.html
摘要:復(fù)合唯一索引也可以創(chuàng)建復(fù)合的唯一索引。中的稀疏索引與關(guān)系型數(shù)據(jù)庫中的稀疏索引是完全不同的概念。但是這里不會(huì)指明索引是否是多鍵索引。上一篇文章指南使用和何時(shí)不應(yīng)該使用索引下一篇文章指南特殊的索引和集合固定集合索引全文本索引 上一篇文章:MongoDB指南---12、使用explain()和hint()、何時(shí)不應(yīng)該使用索引下一篇文章:MongoDB指南---14、特殊的索引和集合:固定集合...
摘要:表示本次查詢使用了索引,具體來說,是使用了和上的索引,。建立索引時(shí),或者是每執(zhí)行次查詢之后,查詢優(yōu)化器都會(huì)重新評(píng)估查詢計(jì)劃。上一篇文章指南使用復(fù)合索引操作符如何使用索引索引對(duì)象和數(shù)組索引基數(shù)下一篇文章指南索引類型 上一篇文章:MongoDB指南---11、使用復(fù)合索引、$操作符如何使用索引、索引對(duì)象和數(shù)組、索引基數(shù)下一篇文章:MongoDB指南---13、索引類型 使用explain...
摘要:表示本次查詢使用了索引,具體來說,是使用了和上的索引,。建立索引時(shí),或者是每執(zhí)行次查詢之后,查詢優(yōu)化器都會(huì)重新評(píng)估查詢計(jì)劃。上一篇文章指南使用復(fù)合索引操作符如何使用索引索引對(duì)象和數(shù)組索引基數(shù)下一篇文章指南索引類型 上一篇文章:MongoDB指南---11、使用復(fù)合索引、$操作符如何使用索引、索引對(duì)象和數(shù)組、索引基數(shù)下一篇文章:MongoDB指南---13、索引類型 使用explain...
摘要:固定集合不能被分片。為固定集合指定文檔數(shù)量限制時(shí),必須同時(shí)指定固定集合的大小。沒有索引的集合默認(rèn)情況下,每個(gè)集合都有一個(gè)索引。 上一篇文章:MongoDB指南---13、索引類型、索引管理下一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件 本章介紹MongoDB中一些特殊的集合和索引類型,包括: 用于類隊(duì)列數(shù)據(jù)的固定集合(capped...
摘要:固定集合不能被分片。為固定集合指定文檔數(shù)量限制時(shí),必須同時(shí)指定固定集合的大小。沒有索引的集合默認(rèn)情況下,每個(gè)集合都有一個(gè)索引。 上一篇文章:MongoDB指南---13、索引類型、索引管理下一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件 本章介紹MongoDB中一些特殊的集合和索引類型,包括: 用于類隊(duì)列數(shù)據(jù)的固定集合(capped...
閱讀 3280·2023-04-26 02:09
閱讀 2574·2021-11-24 09:39
閱讀 3268·2021-11-16 11:52
閱讀 3614·2021-10-26 09:50
閱讀 2771·2021-10-08 10:05
閱讀 2456·2021-09-22 15:25
閱讀 3299·2019-08-30 13:14
閱讀 908·2019-08-29 17:06