搜尋
首頁資料庫MongoDB帶你聊聊MongoDB中豐富的索引類型

帶你聊聊MongoDB中豐富的索引類型

Feb 17, 2022 am 10:58 AM
mongodb索引類型

這篇文章帶你了解MongoDB,介紹一下MongoDB中豐富的索引類型,希望對大家有幫助!

帶你聊聊MongoDB中豐富的索引類型

MongoDB的索引和MySql的索引的作用和最佳化要遵循的原則基本上相似,MySql索引類型基本上可以區分為:

  • 單鍵索引- 聯合索引
  • 主鍵索引(叢集索引) - 非主鍵索引(非叢集索引)

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欄位,建立單鍵索引,MongoDB會自動將這個索引命名為username_1

#
db.users.createIndex({username:1})
&#39;username_1&#39;

在建立索引後查看一下使用username欄位的查詢計畫,stageIXSCAN代表使用使用了索引掃描

db.users.find({username:"user40001"}).explain()
{ 
   queryPlanner: 
   { 
     winningPlan: 
     { 
        ......
        stage: &#39;FETCH&#39;,
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { username: 1 },
           indexName: &#39;username_1&#39;,
           ......
        } 
     }
     rejectedPlans: [] ,
   },
   ......
   ok: 1 
}

        在索引最佳化的原則當中,有很重要的原則就是索引要建立在基數高的的字段上,所謂基數就是一個字段上不重複數值的個數,即我們在創建users集合時年齡出現的數值是0-99那麼age這個欄位將會有100個不重複的數值,即age欄位的基數為100,而sex這個欄位只會出現0 | 1這個兩個值,即sex欄位的基礎是2,這是一個相當低的基數,在這種情況下,索引的效率並不高並且會導致索引失效.

下面就船艦一個sex字段索引,來查詢執行計劃會發現,查詢時是走的全表掃描,而沒有走相關索引.

db.users.createIndex({sex:1})
&#39;sex_1&#39;

db.users.find({sex:1}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;COLLSCAN&#39;,
        filter: { sex: { &#39;$eq&#39;: 1 } },
        direction: &#39;forward&#39; 
     },
     rejectedPlans: [] 
  },
  ......
  ok: 1 
}

聯合索引

#即索引上會有多個欄位,下面使用agesex兩個欄位建立一個索引

db.users.createIndex({age:1,sex:1})
&#39;age_1_sex_1&#39;

然後我們使用這兩個欄位進行一次查詢,檢視執行計畫,順利地走了這條索引

db.users.find({age:23,sex:1}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { age: 1, sex: 1 },
           indexName: &#39;age_1_sex_1&#39;,
           .......
           indexBounds: { age: [ &#39;[23, 23]&#39; ], sex: [ &#39;[1, 1]&#39; ] } 
        } 
     },
     rejectedPlans: [], 
  },
  ......
  ok: 1 
 }

數組索引

數組索引就是對數組字段創建索引,也叫做多值索引,下面為了​​測試將users集合中的資料增加一部分數組字段.

db.users.updateOne({username:"user1"},{$set:{hobby:["唱歌","篮球","rap"]}})
......

建立陣列索引並進行檢視其執行計劃,注意isMultiKey: true表示使用的索引是多值索引.

db.users.createIndex({hobby:1})
&#39;hobby_1&#39;

db.users.find({hobby:{$elemMatch:{$eq:"钓鱼"}}}).explain()
{ 
   queryPlanner: 
   { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        filter: { hobby: { &#39;$elemMatch&#39;: { &#39;$eq&#39;: &#39;钓鱼&#39; } } },
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { hobby: 1 },
           indexName: &#39;hobby_1&#39;,
           isMultiKey: true,
           multiKeyPaths: { hobby: [ &#39;hobby&#39; ] },
           ......
           indexBounds: { hobby: [ &#39;["钓鱼", "钓鱼"]&#39; ] } } 
         },
     rejectedPlans: [] 
  },
  ......
  ok: 1 
}

        陣列索引相比於其它索引來說索引條目和體積必然呈倍數增加,例如平均每個文檔的hobby數組的size為10,那麼這個集合的hobby數組索引的條目數量將是普通索引的10倍.

聯合數組索引

        聯合數組索引是含有數組字段的聯合索引,這種索引不支持一個索引中含有多個數組字段,即一個索引中最多能有一個數組字段,這是為了避免索引條目爆炸式增長,假設一個索引中有兩個數組字段,那麼這個索引條目的數量將是普通索引的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]
            }
        }
    });
}

建立一個二維空間索引

db.users.createIndex({location:"2dsphere"})
&#39;location_2dsphere&#39;

//查询500米内的人
db.users.find({
  location:{
    $near:{
      $geometry:{type:"Point",coordinates:[102,41.5]},
      $maxDistance:500
    }
  }
})

地理空間索引的type有很多包含Ponit(點) | LineString(線) | Polygon (多邊形)

TTL索引

        TTL的全拼法是time to live,主要用於過期資料自動刪除,使用這種索引需要在文檔中聲明一個時間類型的字段,然後為這個字段創建TTL索引的時候還需要設置一個expireAfterSeconds過期時間單位為秒,創建完成後MongoDB會定期對集合中的資料進行檢查,當出現:

#目前時間T##T L索引欄位時間>expi reAfte##rSrcon#ds目前時間- TTL索引欄位時間> expireAfterSrcondsf
t######e### ###r######S######r######c######o######n#####d###### s##################

MongoDB将会自动将这些文档删除,这种索引还有以下这些要求:

  • TTL索引只能有一个字段,没有联合TTL索引
  • TTL不能用于固定集合
  • TTL索引是逐个遍历后,发现满足删除条件会使用delete函数删除,效率并不高

首先在我们文档上增减一个时间字段

for(var i = 90000;i < 100000;i++){
    db.users.updateOne(
    {username:"user"+i},
    {
        $set:{
            createdDate:new Date()
        }
    });
}

创建一个TTL索引并且设定过期时间为60s,待过60s后查询,会发现这些数据已经不存在

db.users.createIndex({createdDate:1},{expireAfterSeconds:60})
&#39;createdDate_1&#39;

另外还可以用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索引,查看执行计划会发现isPartial这个字段会变成true

db.users.createIndex({username:1},{partialFilterExpression:{
    age:{$gt:50}
  }})
&#39;username_1&#39;

db.users.find({$and:[{username:"user4"},{age:60}]}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        filter: { age: { &#39;$eq&#39;: 60 } },
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { username: 1 },
           indexName: &#39;username_1&#39;,
           ......
           isPartial: true,
           ......
         } 
     },
     rejectedPlans: [] 
  },
  ......
  ok: 1 
}

稀疏索引

        一般的索引会根据某个字段为整个集合创建一个索引,即使某个文档不存这个字段,那么这个索引会把这个文档的这个字段当作null建立在索引当中.

稀疏索引不会对文档中不存在的字段建立索引,如果这个字段存在但是为null时,则会创建索引.

下面给users集合中的部分数据创建稀疏索引

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}条件进行查询时,我们会发现查出来的文档包含没有email字段的文档

db.users.find({email:null})
{ 
  _id: ObjectId("61bdc01ba59136670f6536fd"),
  username: &#39;user0&#39;,
  age: 64.41483801726282,
  sex: 0,
  phone: 18468150001,
  location: 
  { 
    type: &#39;Point&#39;,
    coordinates: [ 101.42490900320335, 42.2576650823515 ] 
  } 
}
......

        然后对email这个字段创建一个稀疏索引使用{email:null}条件进行查询,则发现查询来的文档全部是email字段存在且为null的文档.

db.users.createIndex({email:1},{sparse:true});
&#39;email_1&#39;

db.users.find({email:null}).hint({email:1})
{ 
  _id: ObjectId("61bdc12ca59136670f655a25"),
  username: &#39;user9000&#39;,
  age: 94.18397576757012,
  sex: 0,
  phone: 18468159001,
  hobby: [ &#39;钓鱼&#39;, &#39;乒乓球&#39; ],
  location: 
  { 
    type: &#39;Point&#39;,
    coordinates: [ 101.25903151863596, 41.38450145025062 ] 
  },
  email: null 
}
......

文本索引

文本索引将建立索引的文档字段先进行分词再进行检索,但是目前还不支持中文分词.

下面增加两个文本字段,创建一个联合文本索引

db.blog.insertMany([
  {title:"hello world",content:"mongodb is the best database"},
  {title:"index",content:"efficient data structure"}
])

//创建索引
db.blog.createIndex({title:"text",content:"text"})
&#39;title_text_content_text&#39;
//使用文本索引查询
db.blog.find({$text:{$search:"hello data"}})
{ 
  _id: ObjectId("61c092268c4037d17827d977"),
  title: &#39;index&#39;,
  content: &#39;efficient data structure&#39; 
},
{ 
  _id: ObjectId("61c092268c4037d17827d976"),
  title: &#39;hello world&#39;,
  content: &#39;mongodb is the best database&#39; 
}

唯一索引

        唯一索引就是在建立索引地字段上不能出现重复元素,除了单字段唯一索引还有联合唯一索引以及数组唯一索引(即数组之间不能有元素交集 )

//对title字段创建唯一索引
db.blog.createIndex({title:1},{unique:true})
&#39;title_1&#39;
//插入一个已经存在的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" }
//查看一下执行计划,isUnique为true
db.blog.find({"title":"index"}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { title: 1 },
           indexName: &#39;title_1&#39;,
           isMultiKey: false,
           multiKeyPaths: { title: [] },
           isUnique: true,
           ......
         } 
     },
     rejectedPlans: [] 
  },
  .......
  ok: 1 
}

相关视频教程推荐:《MongoDB教程

以上是帶你聊聊MongoDB中豐富的索引類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金社区。如有侵權,請聯絡admin@php.cn刪除
MongoDB與Oracle:了解關鍵差異MongoDB與Oracle:了解關鍵差異Apr 16, 2025 am 12:01 AM

MongoDB适合处理大规模非结构化数据,Oracle适用于需要事务一致性的企业级应用。1.MongoDB提供灵活性和高性能,适合处理用户行为数据。2.Oracle以稳定性和强大功能著称,适用于金融系统。3.MongoDB使用文档模型,Oracle使用关系模型。4.MongoDB适合社交媒体应用,Oracle适合企业级应用。

MongoDB:擴展和績效注意事項MongoDB:擴展和績效注意事項Apr 15, 2025 am 12:02 AM

MongoDB在擴展性和性能方面的考慮包括水平擴展、垂直擴展和性能優化。 1.水平擴展通過分片技術實現,提高系統容量。 2.垂直擴展通過增加硬件資源提升性能。 3.性能優化通過合理設計索引和優化查詢策略實現。

MongoDB的力量:現代數據管理MongoDB的力量:現代數據管理Apr 13, 2025 am 12:04 AM

MongoDB是一種NoSQL數據庫,因其靈活性和可擴展性在現代數據管理中非常重要。它採用文檔存儲,適合處理大規模、多變的數據,並提供強大的查詢和索引能力。

mongodb怎麼批量刪除mongodb怎麼批量刪除Apr 12, 2025 am 09:27 AM

MongoDB 中批量刪除文檔可以使用以下方法:1. $in 操作符指定要刪除的文檔列表;2. 正則表達式匹配符合條件的文檔;3. $exists 操作符刪除具有指定字段的文檔;4. find() 和 remove() 方法先獲取再刪除文檔。請注意,這些操作無法使用事務,並可能刪除所有匹配的文檔,因此使用時需謹慎。

mongodb命令怎麼設置mongodb命令怎麼設置Apr 12, 2025 am 09:24 AM

要設置MongoDB數據庫,可以使用命令行(use和db.createCollection())或mongo Shell(mongo、use和db.createCollection())。其他設置選項包括查看數據庫(show dbs)、查看集合(show collections)、刪除數據庫(db.dropDatabase())、刪除集合(db.&lt;collection_name&gt;.drop())、插入文檔(db.&lt;collecti

怎麼部署mongodb集群怎麼部署mongodb集群Apr 12, 2025 am 09:21 AM

部署 MongoDB 集群分五步:部署主節點,部署輔助節點,添加輔助節點,配置複製,驗證集群。包括安裝 MongoDB 軟件、創建數據目錄、啟動 MongoDB 實例、初始化複製集、添加輔助節點、啟用副本集功能、配置投票權,並驗證集群狀態和數據複製。

mongodb應用場景怎麼用mongodb應用場景怎麼用Apr 12, 2025 am 09:18 AM

MongoDB 廣泛應用於以下場景:文檔存儲:管理用戶資料、內容、產品目錄等結構化和非結構化數據。實時分析:快速查詢和分析日誌、監控儀錶盤展示等實時數據。社交媒體:管理用戶關係圖譜、活動流和消息傳遞。物聯網:處理設備監控、數據收集和遠程管理等海量時間序列數據。移動應用:作為後端數據庫,同步移動設備數據、提供離線存儲等。其他領域:電子商務、醫療保健、金融服務和遊戲開發等多樣化場景。

怎麼看mongodb版本怎麼看mongodb版本Apr 12, 2025 am 09:15 AM

如何查看 MongoDB 版本:命令行:使用 db.version() 命令。編程語言驅動程序:Python:print(client.server_info()["version"])Node.js:db.command({ version: 1 }, (err, result) => { console.log(result.version); });

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器