? ??? MongoDB? ???? MongoDB? ??? ??? ??? ???? ? ??? ? ????.
MongoDB
? ???? MySql
? ???? ????? ??? ??? ??? ???, MySql? ????? ?? ?????. <code>MongoDB
的索引和MySql
的索引的作用和優(yōu)化要遵循的原則基本相似,MySql
索引類型基本可以區(qū)分為:
- 單鍵索引 - 聯(lián)合索引
- 主鍵索引(聚簇索引) - 非主鍵索引(非聚簇索引)
在MongoDB
中除了這些基礎的分類之外,還有一些特殊的索引類型,如: 數組索引 | 稀疏索引 | 地理空間索引 | TTL索引等.
為了下面方便測試我們使用腳本插入以下數據
for(var i = 0;i < 100000;i++){ db.users.insertOne({ username: "user"+i, age: Math.random() * 100, sex: i % 2, phone: 18468150001+i }); }
單鍵索引
單鍵索引即索引的字段只有一個,是最基礎的索引方式.
在集合中使用username
字段,創(chuàng)建一個單鍵索引,MongoDB
會自動將這個索引命名為username_1
db.users.createIndex({username:1}) 'username_1'
在創(chuàng)建索引后查看一下使用username
字段的查詢計劃,stage
為IXSCAN
代表使用使用了索引掃描
db.users.find({username:"user40001"}).explain() { queryPlanner: { winningPlan: { ...... stage: 'FETCH', inputStage: { stage: 'IXSCAN', keyPattern: { username: 1 }, indexName: 'username_1', ...... } } rejectedPlans: [] , }, ...... ok: 1 }
在索引優(yōu)化的原則當中,有很重要的原則就是索引要建立在基數高的的字段上,所謂基數就是一個字段上不重復數值的個數,即我們在創(chuàng)建users
集合時年齡出現的數值是0-99
那么age
這個字段將會有100個不重復的數值,即age
字段的基數為100,而sex
這個字段只會出現0 | 1
這個兩個值,即sex
字段的基礎是2,這是一個相當低的基數,在這種情況下,索引的效率并不高并且會導致索引失效.
下面就船艦一個sex
字段索引,來查詢執(zhí)行計劃會發(fā)現,查詢時是走的全表掃描,而沒有走相關索引.
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)合索引
聯(lián)合索引即索引上會有多個字段,下面使用age
和sex
兩個字段創(chuàng)建一個索引
db.users.createIndex({age:1,sex:1}) 'age_1_sex_1'
然后我們使用這兩個字段進行一次查詢,查看執(zhí)行計劃,順利地走了這條索引
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 }
數組索引
數組索引就是對數組字段創(chuàng)建索引,也叫做多值索引,下面為了測試將users
集合中的數據增加一部分數組字段.
db.users.updateOne({username:"user1"},{$set:{hobby:["唱歌","籃球","rap"]}}) ......
創(chuàng)建數組索引并進行查看其執(zhí)行計劃,注意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 }
數組索引相比于其它索引來說索引條目和體積必然呈倍數增加,例如平均每個文檔的hobby
數組的size
為10,那么這個集合的hobby
數組索引的條目數量將是普通索引的10倍.
聯(lián)合數組索引
聯(lián)合數組索引就是含有數組字段的聯(lián)合索引,這種索引不支持一個索引中含有多個數組字段,即一個索引中最多能有一個數組字段,這是為了避免索引條目爆炸式增長,假設一個索引中有兩個數組字段,那么這個索引條目的數量將是普通索引的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] } } }); }
創(chuàng)建一個二維空間索引
db.users.createIndex({location:"2dsphere"}) 'location_2dsphere' //查詢500米內的人 db.users.find({ location:{ $near:{ $geometry:{type:"Point",coordinates:[102,41.5]}, $maxDistance:500 } } })
地理空間索引的type
有很多包含Ponit(點)
| LineString(線)
| Polygon(多邊形)
等
TTL索引
TTL的全拼是time to live
,主要是用于過期數據自動刪除,使用這種索引需要在文檔中聲明一個時間類型的字段,然后為這個字段創(chuàng)建TTL索引的時候還需要設置一個expireAfterSeconds
過期時間單位為秒,創(chuàng)建完成后MongoDB
- ?? ? ??? - ?? ???
- ?? ? ???(????? ???) - ??? ? ???(?????? ???)< /li>
for(var i = 90000;i < 100000;i++){ db.users.updateOne( {username:"user"+i}, { $set:{ createdDate:new Date() } }); }
?? ? ???
???? ? ???? ??? ?????. ?? ???? ?? ??? ?? ??? ??? ????.???? ????username
??? ???? ?? ? ??? ???? MongoDB
? ???? ??? ?????. ? ???? username_1
??db.users.createIndex({createdDate:1},{expireAfterSeconds:60}) 'createdDate_1'?????? ??? ?
username
??? ??? ?? ??? IXSCAN</code?? ?????. > ??? ??? ????? ??????<pre class='brush:php;toolbar:false;'>db.runCommand({
collMod:"users",
index:{
keyPattern:{createdDate:1},
expireAfterSeconds:120
}
})
{ expireAfterSeconds_old: 60, expireAfterSeconds_new: 120, ok: 1 }</pre>?? ??? ???? ?? ?? ?? ??? ??? ???? ?????? ?? ??? ????? ??? ????. ?, <code>users
???? ??? ? ???? age ?? 0-99
?? age???.
???? 100?? ?? ?? ????. ?, age
??? ?? ?? 100?? sex
? ???? 2?? ?? ???? ??< code>0 | 1, ? sex
??? ??? 2?? ?? ??? ?? ?????. ? ?? ??? ???? ?? ??? ??? ?? ??? ?????. ???? sex
?? ???? ???? ?? ??? ??? ?????. ??? ?? ???? ???? ?? ?? ??? ??? ?????.??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 }
?? ???
???? ???? ???? ?? ??? ??? ?????. ???age<? ???? /code> ? ??? ???? ???? ?????. ? <code>sex
??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}} ) } }?? ?? ?? ? ? ??? ???? ??? ???? ?? ??? ??? ? ? ???? ????? ????? ??
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 ] } } ......
?? ???
???? ???? ?? ? ?????? ?? ?? ??? ???? ???? ????. ??? ???? ???users
???? ?????. ???? ?? ?? ??? ?????. ??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 } ......???? ???? ???? ?? ?? ??? ???.
isMultiKey: true
? ??? ???? ?? ? ????? ?????. ????? ??? ??? ??? ??????? ???? ???. ?? ?? ? ??? hobby
??? ?? size
? 10?? ? ??
? ???? ?? ??? ?? ?? ?? ???? 10????. ????Associated Array Index???? ?????????????????????????????????????????????????????~?????? ??? ?? ???? ??? ???? ??? ??????. ? ??? ???? ??? ???? ?? ??? ???? ????. ?, ??? ??? ? ?? ???? ?? ???? ?? ????. ???? ?? ?? ?? ?? ??? n*m ??? ?????< h3 data-id="heading-3">???? ???? ?? users
???? ?? ??? ???????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' }??? ?? ?? ?? ??? ?????
//對title字段創(chuàng)建唯一索引 db.blog.createIndex({title:1},{unique:true}) 'title_1' //插入一個已經存在的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í)行計劃,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 }???? ?? ????
type
?? ?? Ponit(point)? ???? ????
| LineString(line)
| Polygon( ???)
???TTL ??? Strong>
?? TTL? ?? ???time to live
??, ?? ??? ???? ???? ???? ? ?????. ??? ???? ? ??? ?? TTL ???? ??? ? expireAfterSeconds
?? ?? ??? ?? ???? ???. ??? ??? ? MongoDB
? ????? ???? ???? ?????. ??: ??MongoDB
將會自動將這些文檔刪除,這種索引還有以下這些要求:
- TTL索引只能有一個字段,沒有聯(lián)合TTL索引
- TTL不能用于固定集合
- TTL索引是逐個遍歷后,發(fā)現滿足刪除條件會使用
delete
函數刪除,效率并不高
首先在我們文檔上增減一個時間字段
for(var i = 90000;i < 100000;i++){ db.users.updateOne( {username:"user"+i}, { $set:{ createdDate:new Date() } }); }
創(chuàng)建一個TTL索引并且設定過期時間為60s,待過60s后查詢,會發(fā)現這些數據已經不存在
db.users.createIndex({createdDate:1},{expireAfterSeconds:60}) 'createdDate_1'
另外還可以用CollMod
命令更改TTL索引的過期時間
db.runCommand({ collMod:"users", index:{ keyPattern:{createdDate:1}, expireAfterSeconds:120 } }) { expireAfterSeconds_old: 60, expireAfterSeconds_new: 120, ok: 1 }
條件索引
條件索引也叫部分索引(partial),只對滿足條件的數據進行建立索引.
只對50歲以上的user
進行建立username_1
索引,查看執(zhí)行計劃會發(fā)現isPartial
這個字段會變成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 }
稀疏索引
一般的索引會根據某個字段為整個集合創(chuàng)建一個索引,即使某個文檔不存這個字段,那么這個索引會把這個文檔的這個字段當作null
建立在索引當中.
稀疏索引不會對文檔中不存在的字段建立索引,如果這個字段存在但是為null
時,則會創(chuàng)建索引.
下面給users
集合中的部分數據創(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}} ) } }
當不建立索引使用{email:null}
條件進行查詢時,我們會發(fā)現查出來的文檔包含沒有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 ] } } ......
然后對email
這個字段創(chuàng)建一個稀疏索引使用{email:null}
條件進行查詢,則發(fā)現查詢來的文檔全部是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 } ......
文本索引
文本索引將建立索引的文檔字段先進行分詞再進行檢索,但是目前還不支持中文分詞.
下面增加兩個文本字段,創(chuàng)建一個聯(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' }
唯一索引
唯一索引就是在建立索引地字段上不能出現重復元素,除了單字段唯一索引還有聯(lián)合唯一索引以及數組唯一索引(即數組之間不能有元素交集 )
//對title字段創(chuàng)建唯一索引 db.blog.createIndex({title:1},{unique:true}) 'title_1' //插入一個已經存在的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í)行計劃,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 }
相關視頻教程推薦:《MongoDB教程》
? ??? MongoDB? ??? ??? ??? ?? ???? ?????.? ?? ?????. ??? ??? PHP ??? ????? ?? ?? ??? ?????!

? AI ??

Undress AI Tool
??? ???? ??

Undresser.AI Undress
???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover
???? ?? ???? ??? AI ?????.

Clothoff.io
AI ? ???

Video Face Swap
??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

?? ??

??? ??

???++7.3.1
???? ?? ?? ?? ???

SublimeText3 ??? ??
??? ??, ???? ?? ????.

???? 13.0.1 ???
??? PHP ?? ?? ??

???? CS6
??? ? ?? ??

SublimeText3 Mac ??
? ??? ?? ?? ?????(SublimeText3)

??? ??











?? ??? ? ???? ??? ? ??? ??? ??????. ????? ??? ? ?? ?? ??? ???? ??. ???? ??? ?? ????? ????? ??? ????? ???? ??? ????? ??? ?????. ?? ???? ???? ???? ????? ???? ???? ???? ????? ??????. ????? Composer? ?? Andres-Montanez/Residations-Bundle? ???? ??? ?????? ??? ?? ???? ??? ?? ?? ?????. ?? ??? ?? ???? ?? ? ????.

CentOS ???? GitLab ?????? ?? ??? ??? ??????? ???? ?? GitLab? ????? ???? ? ??? ?????. Gitlab? MySQL, PostgreSQL ? MongoDB? ??? ??? ??????? ?????. ? ??? ??? ??????? ???? ???? ??? ??? ?????. ?????? ?? ?? ?? MySQL : ?? ???? RDBMS (Relational Database Management System). PostgreSQL : ??? ?? ?? RDBM? ??? ?? ? ?? ??? ???? ?? ??? ??? ???? ? ?????. MongoDB : ???? NOSQL ??????, ?? ??? ?????

MongoDB? ??? ??? ???? ???? ? ???? Oracle? ?? ???? ??? ?????? ??? ?? ????? ?????. 1. MongoDB? ??? ?? ??? ??? ??? ???? ???? ?????. 2. Oracle? ???? ??? ???? ???? ?? ???? ?????. 3. MongoDB? ?? ??? ???? Oracle? ??? ??? ?????. 4. MongoDB? ?? ??? ?? ????? ????? Oracle? ?????? ??? ?? ????? ?????.

MongoDB? ????? ?? ??? ? ?? ?? ? ?? ??? ??? ?? Oracle? ??? ??? ???? ??? ????? ?????. 1. MongoDB? ?? ??? ? ?? ???? ??? ??? ???? ???? ???? ?????. 2. Oracle ??? ? ??? ??? ??? ???? ???? ?? ??? ?????. 3. MongoDB? ??? ?? ???? ???, RAC? ?? ???? ??? ???????. 4. MongoDB? ?? ?? ??? ?? ? Oracle? ?? ?? ??? ??? ??? ?????.

CentOS ??? ??? MongoDB ???? ?? ??? ?? ??? ??? ??? CentOS ????? MongoDB ??? ?????? ??? ??? ??? ???? ??? ?? ? ???? ???? ?? ? ????. Docker ???? ???? ?? ??, ??? ??? ??, ?? ???? ?? ? ?? ???? ??? ?? ?? ????? ?? ??? ?????. ?? ?? : MongoDump ??? ???? Manual ?? ??? ?????? (? : Mongodump-HlocalHost : 27017-U username-P password-d ?????? ?? -o/?? ????? ??? ??? ??????? ??? ? ?? ???? ??? ?? ????? ???????.

MongoDB ???? ????? ?? ??? ?????. 1. ??? ???? ??? ???? ????. 2. ????? ??? ??? ?? ? ??????? ??????. 3. CreateUser ??? ???? ???? ???? ??? ?? ? ?????? ??? ??? ??????. 4. GetUsers ??? ???? ?? ? ???? ??????. 5. ????? ?? ???? ?? ?? ??? ????? ??? ??? ?????.

??? ????? MongoDB ??????? ?????? ?? ??? ?? ?????. 1 ?? : ?? MongoDB ?? ?? Debian ???? MongoDB? ???? ??? ??????. ??? ?? ?? ????? ?? MongoDB ??? ?????? : https://docs.mongodb.com/manual/tutorial/install-mongodb-ondodb-on-debian/step 2 : ??? ? ?? ?? ??? ?? ???? ??? ????.
