這篇文章帶你了解MongoDB,介紹一下MongoDB中豐富的索引類型,希望對(duì)大家有幫助!
MongoDB
的索引和MySql
的索引的作用和最佳化要遵循的原則基本上相似,MySql
索引類型基本上可以區(qū)分為:
- 單鍵索引- 聯(lián)合索引
- 主鍵索引(叢集索引) - 非主鍵索引(非叢集索引)
在MongoDB
中除了這些基礎(chǔ)的分類之外,還有一些特殊的索引類型,如: 數(shù)組索引| 稀疏索引| 地理空間索引| TTL索引等.
為了下面方便測試我們使用腳本插入以下資料
for(var i = 0;i < 100000;i++){ db.users.insertOne({ username: "user"+i, age: Math.random() * 100, sex: i % 2, phone: 18468150001+i }); }
單鍵索引
單鍵索引即索引的欄位只有一個(gè),是最基礎(chǔ)的索引方式.
在集合中使用username
欄位,建立單鍵索引,MongoDB
會(huì)自動(dòng)將這個(gè)索引命名為username_1
db.users.createIndex({username:1}) 'username_1'
在建立索引後查看一下使用username
欄位的查詢計(jì)畫,stage
為IXSCAN
代表使用使用了索引掃描
db.users.find({username:"user40001"}).explain() { queryPlanner: { winningPlan: { ...... stage: 'FETCH', inputStage: { stage: 'IXSCAN', keyPattern: { username: 1 }, indexName: 'username_1', ...... } } rejectedPlans: [] , }, ...... ok: 1 }
? ? ? ? 在索引最佳化的原則當(dāng)中,有很重要的原則就是索引要建立在基數(shù)高的的字段上,所謂基數(shù)就是一個(gè)字段上不重複數(shù)值的個(gè)數(shù),即我們?cè)趧?chuàng)建users
集合時(shí)年齡出現(xiàn)的數(shù)值是0-99
那麼age
這個(gè)欄位將會(huì)有100個(gè)不重複的數(shù)值,即age
欄位的基數(shù)為100,而sex
這個(gè)欄位只會(huì)出現(xiàn)0 | 1
這個(gè)兩個(gè)值,即sex
欄位的基礎(chǔ)是2,這是一個(gè)相當(dāng)?shù)偷幕鶖?shù),在這種情況下,索引的效率並不高並且會(huì)導(dǎo)致索引失效.
下面就船艦一個(gè)sex
字段索引,來查詢執(zhí)行計(jì)劃會(huì)發(fā)現(xiàn),查詢時(shí)是走的全表掃描,而沒有走相關(guān)索引.
db.users.createIndex({sex:1}) 'sex_1' db.users.find({sex:1}).explain() { queryPlanner: { ...... winningPlan: { stage: 'COLLSCAN', filter: { sex: { '$eq': 1 } }, direction: 'forward' }, rejectedPlans: [] }, ...... ok: 1 }
聯(lián)合索引
#即索引上會(huì)有多個(gè)欄位,下面使用age
和sex
兩個(gè)欄位建立一個(gè)索引
db.users.createIndex({age:1,sex:1}) 'age_1_sex_1'
然後我們使用這兩個(gè)欄位進(jìn)行一次查詢,檢視執(zhí)行計(jì)畫,順利地走了這條索引
db.users.find({age:23,sex:1}).explain() { queryPlanner: { ...... winningPlan: { stage: 'FETCH', inputStage: { stage: 'IXSCAN', keyPattern: { age: 1, sex: 1 }, indexName: 'age_1_sex_1', ....... indexBounds: { age: [ '[23, 23]' ], sex: [ '[1, 1]' ] } } }, rejectedPlans: [], }, ...... ok: 1 }
數(shù)組索引
數(shù)組索引就是對(duì)數(shù)組字段創(chuàng)建索引,也叫做多值索引,下面為了??測試將users
集合中的資料增加一部分?jǐn)?shù)組字段.
db.users.updateOne({username:"user1"},{$set:{hobby:["唱歌","籃球","rap"]}}) ......
建立陣列索引並進(jìn)行檢視其執(zhí)行計(jì)劃,注意isMultiKey: true
表示使用的索引是多值索引.
db.users.createIndex({hobby:1}) 'hobby_1' db.users.find({hobby:{$elemMatch:{$eq:"釣魚"}}}).explain() { queryPlanner: { ...... winningPlan: { stage: 'FETCH', filter: { hobby: { '$elemMatch': { '$eq': '釣魚' } } }, inputStage: { stage: 'IXSCAN', keyPattern: { hobby: 1 }, indexName: 'hobby_1', isMultiKey: true, multiKeyPaths: { hobby: [ 'hobby' ] }, ...... indexBounds: { hobby: [ '["釣魚", "釣魚"]' ] } } }, rejectedPlans: [] }, ...... ok: 1 }
? ? ? ? 陣列索引相比於其它索引來說索引條目和體積必然呈倍數(shù)增加,例如平均每個(gè)文檔的hobby
數(shù)組的size
為10,那麼這個(gè)集合的hobby
數(shù)組索引的條目數(shù)量將是普通索引的10倍.
聯(lián)合數(shù)組索引
? ? ? ? 聯(lián)合數(shù)組索引是含有數(shù)組字段的聯(lián)合索引,這種索引不支持一個(gè)索引中含有多個(gè)數(shù)組字段,即一個(gè)索引中最多能有一個(gè)數(shù)組字段,這是為了避免索引條目爆炸式增長,假設(shè)一個(gè)索引中有兩個(gè)數(shù)組字段,那麼這個(gè)索引條目的數(shù)量將是普通索引的n* m倍
地理空間索引
在原先的users
集合上,增加一些地理資訊
for(var i = 0;i < 100000;i++){ db.users.updateOne( {username:"user"+i}, { $set:{ location:{ type: "Point", coordinates: [100+Math.random() * 4,40+Math.random() * 3] } } }); }
建立一個(gè)二維空間索引
db.users.createIndex({location:"2dsphere"}) 'location_2dsphere' //查詢500米內(nèi)的人 db.users.find({ location:{ $near:{ $geometry:{type:"Point",coordinates:[102,41.5]}, $maxDistance:500 } } })
地理空間索引的type
有很多包含Ponit(點(diǎn))
| LineString(線)
| Polygon (多邊形)
等
TTL索引
? ? ? ? TTL的全拼法是time to live
,主要用於過期資料自動(dòng)刪除,使用這種索引需要在文檔中聲明一個(gè)時(shí)間類型的字段,然後為這個(gè)字段創(chuàng)建TTL索引的時(shí)候還需要設(shè)置一個(gè)expireAfterSeconds
過期時(shí)間單位為秒,創(chuàng)建完成後MongoDB
會(huì)定期對(duì)集合中的資料進(jìn)行檢查,當(dāng)出現(xiàn):
MongoDB
將會(huì)自動(dòng)將這些文檔刪除,這種索引還有以下這些要求:
- TTL索引只能有一個(gè)字段,沒有聯(lián)合TTL索引
- TTL不能用于固定集合
- TTL索引是逐個(gè)遍歷后,發(fā)現(xiàn)滿足刪除條件會(huì)使用
delete
函數(shù)刪除,效率并不高
首先在我們文檔上增減一個(gè)時(shí)間字段
for(var i = 90000;i < 100000;i++){ db.users.updateOne( {username:"user"+i}, { $set:{ createdDate:new Date() } }); }
創(chuàng)建一個(gè)TTL索引并且設(shè)定過期時(shí)間為60s,待過60s后查詢,會(huì)發(fā)現(xiàn)這些數(shù)據(jù)已經(jīng)不存在
db.users.createIndex({createdDate:1},{expireAfterSeconds:60}) 'createdDate_1'
另外還可以用CollMod
命令更改TTL索引的過期時(shí)間
db.runCommand({ collMod:"users", index:{ keyPattern:{createdDate:1}, expireAfterSeconds:120 } }) { expireAfterSeconds_old: 60, expireAfterSeconds_new: 120, ok: 1 }
條件索引
條件索引也叫部分索引(partial),只對(duì)滿足條件的數(shù)據(jù)進(jìn)行建立索引.
只對(duì)50歲以上的user
進(jìn)行建立username_1
索引,查看執(zhí)行計(jì)劃會(huì)發(fā)現(xiàn)isPartial
這個(gè)字段會(huì)變成true
db.users.createIndex({username:1},{partialFilterExpression:{ age:{$gt:50} }}) 'username_1' db.users.find({$and:[{username:"user4"},{age:60}]}).explain() { queryPlanner: { ...... winningPlan: { stage: 'FETCH', filter: { age: { '$eq': 60 } }, inputStage: { stage: 'IXSCAN', keyPattern: { username: 1 }, indexName: 'username_1', ...... isPartial: true, ...... } }, rejectedPlans: [] }, ...... ok: 1 }
稀疏索引
一般的索引會(huì)根據(jù)某個(gè)字段為整個(gè)集合創(chuàng)建一個(gè)索引,即使某個(gè)文檔不存這個(gè)字段,那么這個(gè)索引會(huì)把這個(gè)文檔的這個(gè)字段當(dāng)作null
建立在索引當(dāng)中.
稀疏索引不會(huì)對(duì)文檔中不存在的字段建立索引,如果這個(gè)字段存在但是為null
時(shí),則會(huì)創(chuàng)建索引.
下面給users
集合中的部分?jǐn)?shù)據(jù)創(chuàng)建稀疏索引
for(var i = 5000;i < 10000;i++){ if(i < 9000){ db.users.updateOne( {username:"user"+i}, { $set:{email:(120000000+i)+"@qq.email"}} ) }else{ db.users.updateOne( {username:"user"+i}, { $set:{email:null}} ) } }
當(dāng)不建立索引使用{email:null}
條件進(jìn)行查詢時(shí),我們會(huì)發(fā)現(xiàn)查出來的文檔包含沒有email
字段的文檔
db.users.find({email:null}) { _id: ObjectId("61bdc01ba59136670f6536fd"), username: 'user0', age: 64.41483801726282, sex: 0, phone: 18468150001, location: { type: 'Point', coordinates: [ 101.42490900320335, 42.2576650823515 ] } } ......
然后對(duì)email
這個(gè)字段創(chuàng)建一個(gè)稀疏索引使用{email:null}
條件進(jìn)行查詢,則發(fā)現(xiàn)查詢來的文檔全部是email
字段存在且為null
的文檔.
db.users.createIndex({email:1},{sparse:true}); 'email_1' db.users.find({email:null}).hint({email:1}) { _id: ObjectId("61bdc12ca59136670f655a25"), username: 'user9000', age: 94.18397576757012, sex: 0, phone: 18468159001, hobby: [ '釣魚', '乒乓球' ], location: { type: 'Point', coordinates: [ 101.25903151863596, 41.38450145025062 ] }, email: null } ......
文本索引
文本索引將建立索引的文檔字段先進(jìn)行分詞再進(jìn)行檢索,但是目前還不支持中文分詞.
下面增加兩個(gè)文本字段,創(chuàng)建一個(gè)聯(lián)合文本索引
db.blog.insertMany([ {title:"hello world",content:"mongodb is the best database"}, {title:"index",content:"efficient data structure"} ]) //創(chuàng)建索引 db.blog.createIndex({title:"text",content:"text"}) 'title_text_content_text' //使用文本索引查詢 db.blog.find({$text:{$search:"hello data"}}) { _id: ObjectId("61c092268c4037d17827d977"), title: 'index', content: 'efficient data structure' }, { _id: ObjectId("61c092268c4037d17827d976"), title: 'hello world', content: 'mongodb is the best database' }
唯一索引
唯一索引就是在建立索引地字段上不能出現(xiàn)重復(fù)元素,除了單字段唯一索引還有聯(lián)合唯一索引以及數(shù)組唯一索引(即數(shù)組之間不能有元素交集 )
//對(duì)title字段創(chuàng)建唯一索引 db.blog.createIndex({title:1},{unique:true}) 'title_1' //插入一個(gè)已經(jīng)存在的title值 db.blog.insertOne({title:"hello world",content:"mongodb is the best database"}) MongoServerError: E11000 duplicate key error collection: mock.blog index: title_1 dup key: { : "hello world" } //查看一下執(zhí)行計(jì)劃,isUnique為true db.blog.find({"title":"index"}).explain() { queryPlanner: { ...... winningPlan: { stage: 'FETCH', inputStage: { stage: 'IXSCAN', keyPattern: { title: 1 }, indexName: 'title_1', isMultiKey: false, multiKeyPaths: { title: [] }, isUnique: true, ...... } }, rejectedPlans: [] }, ....... ok: 1 }
相關(guān)視頻教程推薦:《MongoDB教程》
以上是帶你聊聊MongoDB中豐富的索引類型的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級(jí)程式碼編輯軟體(SublimeText3)

熱門話題

在開發(fā)一個(gè)電商網(wǎng)站時(shí),我遇到了一個(gè)棘手的問題:如何為用戶提供個(gè)性化的商品推薦。最初,我嘗試了一些簡單的推薦算法,但效果並不理想,用戶的滿意度也因此受到影響。為了提升推薦系統(tǒng)的精度和效率,我決定採用更專業(yè)的解決方案。最終,我通過Composer安裝了andres-montanez/recommendations-bundle,這不僅解決了我的問題,還大大提升了推薦系統(tǒng)的性能??梢酝ㄟ^一下地址學(xué)習(xí)composer:學(xué)習(xí)地址

CentOS系統(tǒng)上GitLab數(shù)據(jù)庫部署指南選擇合適的數(shù)據(jù)庫是成功部署GitLab的關(guān)鍵步驟。 GitLab兼容多種數(shù)據(jù)庫,包括MySQL、PostgreSQL和MongoDB。本文將詳細(xì)介紹如何選擇並配置這些數(shù)據(jù)庫。數(shù)據(jù)庫選擇建議MySQL:一款廣泛應(yīng)用的關(guān)係型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),性能穩(wěn)定,適用於大多數(shù)GitLab部署場景。 PostgreSQL:功能強(qiáng)大的開源RDBMS,支持複雜查詢和高級(jí)特性,適合處理大型數(shù)據(jù)集。 MongoDB:流行的NoSQL數(shù)據(jù)庫,擅長處理海

MongoDB適合處理大規(guī)模非結(jié)構(gòu)化數(shù)據(jù),Oracle適用于需要事務(wù)一致性的企業(yè)級(jí)應(yīng)用。1.MongoDB提供靈活性和高性能,適合處理用戶行為數(shù)據(jù)。2.Oracle以穩(wěn)定性和強(qiáng)大功能著稱,適用于金融系統(tǒng)。3.MongoDB使用文檔模型,Oracle使用關(guān)系模型。4.MongoDB適合社交媒體應(yīng)用,Oracle適合企業(yè)級(jí)應(yīng)用。

MongoDB適合非結(jié)構(gòu)化數(shù)據(jù)和高擴(kuò)展性需求,Oracle適合需要嚴(yán)格數(shù)據(jù)一致性的場景。 1.MongoDB靈活存儲(chǔ)不同結(jié)構(gòu)數(shù)據(jù),適合社交媒體和物聯(lián)網(wǎng)。 2.Oracle結(jié)構(gòu)化數(shù)據(jù)模型確保數(shù)據(jù)完整性,適用於金融交易。 3.MongoDB通過分片橫向擴(kuò)展,Oracle通過RAC縱向擴(kuò)展。 4.MongoDB維護(hù)成本低,Oracle維護(hù)成本高但支持完善。

CentOS系統(tǒng)下MongoDB高效備份策略詳解本文將詳細(xì)介紹在CentOS系統(tǒng)上實(shí)施MongoDB備份的多種策略,以確保數(shù)據(jù)安全和業(yè)務(wù)連續(xù)性。我們將涵蓋手動(dòng)備份、定時(shí)備份、自動(dòng)化腳本備份以及Docker容器環(huán)境下的備份方法,並提供備份文件管理的最佳實(shí)踐。手動(dòng)備份:利用mongodump命令進(jìn)行手動(dòng)全量備份,例如:mongodump-hlocalhost:27017-u用戶名-p密碼-d數(shù)據(jù)庫名稱-o/備份目錄此命令會(huì)將指定數(shù)據(jù)庫的數(shù)據(jù)及元數(shù)據(jù)導(dǎo)出到指定的備份目錄。

要設(shè)置 MongoDB 用戶,請(qǐng)按照以下步驟操作:1. 連接到服務(wù)器並創(chuàng)建管理員用戶。 2. 創(chuàng)建要授予用戶訪問權(quán)限的數(shù)據(jù)庫。 3. 使用 createUser 命令創(chuàng)建用戶並指定其角色和數(shù)據(jù)庫訪問權(quán)限。 4. 使用 getUsers 命令檢查創(chuàng)建的用戶。 5. 可選地設(shè)置其他權(quán)限或授予用戶對(duì)特定集合的權(quán)限。

要啟動(dòng) MongoDB 服務(wù)器:在 Unix 系統(tǒng)中,運(yùn)行 mongod 命令。在 Windows 系統(tǒng)中,運(yùn)行 mongod.exe 命令??蛇x:使用 --dbpath、--port、--auth 或 --replSet 選項(xiàng)設(shè)置配置。使用 mongo 命令驗(yàn)證連接是否成功。

在Debian系統(tǒng)上為MongoDB數(shù)據(jù)庫加密,需要遵循以下步驟:第一步:安裝MongoDB首先,確保您的Debian系統(tǒng)已安裝MongoDB。如果沒有,請(qǐng)參考MongoDB官方文檔進(jìn)行安裝:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-debian/第二步:生成加密密鑰文件創(chuàng)建一個(gè)包含加密密鑰的文件,並設(shè)置正確的權(quán)限:ddif=/dev/urandomof=/etc/mongodb-keyfilebs=512
