搜尋
首頁資料庫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在行動:現實世界中用例MongoDB在行動:現實世界中用例May 11, 2025 am 12:18 AM

MongoDB在實際項目中的用法包括:1)文檔存儲,2)複雜的聚合操作,3)性能優化和最佳實踐。具體來說,MongoDB的文檔模型支持靈活的數據結構,適合處理用戶生成內容;聚合框架可用於分析用戶行為;性能優化可以通過索引優化、分片和緩存實現,最佳實踐包括文檔設計、數據遷移和監控維護。

為什麼要使用mongodb?解釋的優點和好處為什麼要使用mongodb?解釋的優點和好處May 10, 2025 am 12:22 AM

MongoDB是一個開源的NoSQL數據庫,採用文檔模型存儲數據。其優勢包括:1.靈活的數據模型,支持JSON格式存儲,適用於快速迭代開發;2.橫向擴展和高可用性,通過分片實現負載均衡;3.豐富的查詢語言,支持複雜查詢和聚合操作;4.性能和優化,通過索引和內存映射文件系統提升數據訪問速度;5.生態系統和社區支持,提供多種驅動程序和活躍的社區幫助。

MongoDB的目的:靈活的數據存儲和管理MongoDB的目的:靈活的數據存儲和管理May 09, 2025 am 12:20 AM

MongoDB的靈活性體現在:1)能存儲任意結構的數據,2)使用BSON格式,3)支持複雜查詢和聚合操作。這種靈活性使其在處理多變數據結構時表現出色,是現代應用開發的強大工具。

MongoDB與Oracle:許可,功能和福利MongoDB與Oracle:許可,功能和福利May 08, 2025 am 12:18 AM

MongoDB適合處理大規模非結構化數據,採用開源許可證;Oracle適合複雜商業事務,採用商業許可證。 1.MongoDB提供靈活的文檔模型和橫向擴展能力,適合大數據處理。 2.Oracle提供強大的ACID事務支持和企業級功能,適合複雜分析工作負載。選擇時需考慮數據類型、預算和技術資源。

MongoDB與Oracle:探索NOSQL和關係方法MongoDB與Oracle:探索NOSQL和關係方法May 07, 2025 am 12:02 AM

在不同的應用場景下,選擇MongoDB還是Oracle取決於具體需求:1)如果需要處理大量非結構化數據且對數據一致性要求不高,選擇MongoDB;2)如果需要嚴格的數據一致性和復雜查詢,選擇Oracle。

關於MongoDB當前情況的真相關於MongoDB當前情況的真相May 06, 2025 am 12:10 AM

MongoDB當前的表現取決於具體的使用場景和需求。 1)在電商平台中,MongoDB適合存儲商品信息和用戶數據,但處理訂單時可能面臨一致性問題。 2)在內容管理系統中,MongoDB便於存儲文章和評論,但處理大量數據時需使用分片技術。

MongoDB與Oracle:文檔數據庫與關係數據庫MongoDB與Oracle:文檔數據庫與關係數據庫May 05, 2025 am 12:04 AM

引言在現代數據管理的世界裡,選擇合適的數據庫系統對於任何項目來說都是至關重要的。我們常常會面臨一個選擇:是選擇MongoDB這種文檔型數據庫,還是選擇Oracle這種關係型數據庫?今天我將帶你深入探討MongoDB和Oracle之間的差異,幫助你理解它們的優劣勢,並分享我在實際項目中使用它們的經驗。本文將會帶你從基礎知識開始,逐步深入到這兩類數據庫的核心特性、使用場景和性能表現。無論你是剛入門的數據管理者,還是有經驗的數據庫管理員,讀完這篇文章,你將對如何在項目中選擇和使用MongoDB或Ora

MongoDB發生了什麼?探索事實MongoDB發生了什麼?探索事實May 04, 2025 am 12:15 AM

MongoDB仍然是一个强大的数据库解决方案。1)它以灵活性和可扩展性著称,适合存储复杂数据结构。2)通过合理索引和查询优化,可以提升其性能。3)使用聚合框架和分片技术,可以进一步优化和扩展MongoDB的应用。

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脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

EditPlus 中文破解版

EditPlus 中文破解版

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

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。