MongoDB—索引


Index

定義

索引,一個單獨的、存儲在磁盤上的數據結構

mongodb 的索引采用 B-tree 數據結構存儲

  • 易於遍歷,支持相等匹配和范圍查詢

  • 存儲字段的值以及指向其所在文檔的指針

    包含集合中所有文檔的指針(包含數據表中所有記錄的引用指針)

  • 按字段的值排序

mongodb index

  • 在集合級別定義索引,支持在文檔中的任何字段或子字段上建立索引
  • 給某個字段添加索引,可以快速找出在該字段有特定值的文檔,提高查詢速度
  • 如果沒有索引,mongodb必須掃描集合中所有的文檔,以選擇那些符合查詢條件的文檔。一般而言,在查詢文檔時應避免掃描全部文檔,這樣會使查詢速度非常慢
  • 建立索引可以縮小mongodb掃描文檔的數量,提高查詢速度
  • mongodb 可以返回基於索引排序的查詢結果

演示基於索引查詢並排序

_id

  • mongodb 默認會為文檔創建一個_id 字段,並建立唯一索引
  • 不能刪除建立在_id字段上的索引
  • 索引名稱為 _id_

創建索引

db.collection.createIndex

  • 為集合創建索引

  • 如果索引(名稱)已經存在,則不會再次創建

  • 除 collation 選項外,使用 不同的選項 不會創建 具有相同索引規范的 索引,也不會修改這些選項的值

    只能刪除之前的索引,重新使用新的選項創建

  • 使用不同的 collation 選項,可以創建 多個 具有相同的索引規范的 索引,但是需要指定 唯一的 索引名稱

    db.person.createIndex({name:1},{name:"a_c", collation:{locale:"fr"}})
    db.person.createIndex({name:1},{name:"a_b", collation:{locale:"fa"}})
    
  • 如果文檔不包含指定的字段,則操作失敗

格式

db.collection.createIndex(keys, options)
  • keys

    • 類型:Document
    • 描述:
      • 包含字段和值的文檔,其中字段是索引鍵,值是該字段的索引類型

        判斷索引是否相同根據索引的 keys,因此 keys 不同就代表索引不同

        • 用下划線連接組成默認索引名稱

        • 同一個字段上只能創建一個相同類型的索引,可以創建多個不同類型的索引

          例如 {age:1} {age:-1} 兩個keys不同,索引(名)不同

      • 索引類型包括:test、geospatial、hashed、ascending、descending

        排序規則

        • 值為 1,表示升序(ascending)
        • 值為 -1,表示降序(descending)
  • options

    • 類型:Document

    • 描述:創建索引的選項,不同類型的索引有特定於該類型的選項,以下為共有選項

      • background

        • 類型:布爾【4.2版本中被廢棄】

        • 描述:是否在后台執行創建索引的過程,不阻塞對集合的操作

          • false【默認】

            不在后台創建

          • true

            后台創建

        • 4.2 版本中所有的索引構建,使用一個優化的構建過程,它只在構建過程的開始和結束時持有獨占鎖,構建過程中讓步於讀寫操作

          4.2 版本會忽略該選項

        • 4.2 版本之前索引的構建的整個過程都會持有獨占鎖,阻塞數據庫及其所有集合上的操作,直到操作完成,在后台創建索引不會持有獨占鎖

      • unique

        • 類型:布爾

        • 描述:

          • 是否創建具有唯一性的索引

            • true

              此索引具有唯一性,當索引重復時,不接受對文檔的插入或更新

            • false【默認】

          • 不適用於 hashed 索引

      • name

        • 類型:字符串

        • 描述

          • 自定義索引名稱

          • 如果不指定,mongodb將通過 下划線 連接 索引字段的名稱和排序規則 生成一個索引名稱

            例如在 { item : 1, quantity: -1 } 上創建的索引名稱為 item_1_quantity_-1

          • 一旦創建不能修改,只能刪除再重新創建

        4.2 版本之前,索引名最大長度為 127 字節,4.2版本開始取消該限制

      • partialFilterExpression

        • 類型:Document

        • 描述:僅為集合中符合條件的文檔建立索引,降低創建和維護成本

      • sparse

        [spɑrs] 稀疏

        • 類型:布爾

        • 描述:僅為集合中具有指定字段的文檔建立索引

          • true

            建立稀疏索引

          • false 【默認】

          zdsphere、2d、geoHaystack、text 默認為稀疏文檔,忽略此選項

      • expireAfterSeconds

        • 類型:integer,單位 秒
        • 描述:用於 TTL 索引中 控制 文檔保存在集合中的時間
      • storageEngine

        • 類型:Document
        • 描述:指定存儲引擎配置

Returns

  • 成功

    {
    	"createdCollectionAutomatically" : false,
    	"numIndexesBefore" : 3,
    	"numIndexesAfter" : 4,
    	"ok" : 1
    }
    
    • createdCollectionAutomatically 是否自動創建集合
    • numIndexesBefore 創建之前索引個數
    • numIndexesAfter 創建之后索引個數
    • ok:1 創建成功
  • 失敗

    {
    	"ok" : 0,
    	"errmsg" : "Error: hashed indexes do not currently support array values",
    	"code" : 16766,
    	"codeName" : "Location16766"
    }
    
    • ok:0 創建失敗
    • errmsg 失敗信息
    • code 失敗碼
    • codeName ?

查詢索引

db.collection.getIndexes

  • 查詢集合中所有的索引信息

  • 返回一個數組,數組元素是描述索引信息的文檔

    索引信息包括創建索引時的信息:keys 以及 options

格式

db.collection.getIndexes()

db.collection.totalIndexSize

  • 查詢集合中所有索引的大小
  • 如果索引使用前綴壓縮 (這是WiredTiger的默認值),則返回壓縮后的大小
  • 單位 字節 byte

格式

db.collection.totalIndexSize()

刪除索引

db.collection.dropIndex

  • 刪除指定索引
  • 不能刪除默認創建在 _id 字段上的索引

格式

db.collection.dropIndex(index)
  • index

    • 類型:字符串、文檔

    • 描述:指定要刪除的索引

      • 可以指定索引的名稱 或 索引規范文檔

        通過 db.collection.getIndexes() 獲取索引名稱

      • 刪除 text 類型的索引,必須指定索引名稱

        無法通過索引規范文檔找到索引,刪除失敗

      • 4.2 版本開始,不能通過db.collection.dropIndex("*") 刪除所有非 _id 字段上的索引,應該使用db.collection.dropIndexes()

排它鎖

  • 4.2 版本之前,dropIndex 操作在父級數據庫上獲取一個排它鎖,阻塞所有對數據庫及其所有集合的操作,直到操作完成
  • 4.2 版本之后,dropIndex 操作在指定集合上獲取一個排它鎖,阻塞對集合的所有后續操作

示例

  • 通過索引名稱刪除

    db.pets.dropIndex( "cat_-1" )
    
  • 通過索引規范文檔刪除

    db.pets.dropIndex( { "cat" : -1 } )
    

de.collection.dropIndexes

  • 刪除單個或多個索引
  • 不能刪除默認創建在 _id 字段上的索引

格式

db.collection.dropIndex(indexes)
  • indexes

    • 類型:字符串、文檔、字符串數組

    • 描述:需要刪除的索引

      • 刪除_id 之外的所有索引,忽略該參數

      • 刪除單個索引,指定索引的名稱或索引規范文檔,text 類型的索引只能指定名稱

      • 刪除多個索引,通過數組指定索引的名稱

        如果數組中包含不存在的索引,則不刪除任何索引,操作報錯

        4.2 新增

排它鎖

  • 4.2 版本之前,dropIndex 操作在父級數據庫上獲取一個排它鎖,阻塞所有對數據庫及其所有集合的操作,直到操作完成
  • 4.2 版本之后,dropIndex 操作在指定集合上獲取一個排它鎖,阻塞對集合的所有后續操作

示例

  • 刪除_id之外的所有索引

    db.collection.dropIndexes()
    
  • 刪除單個索引

    db.collection.dropIndexes( { a: 1, b: 1 } )
    
    db.collection.dropIndexes( "a_1_b_1" )
    
  • 刪除多個索引

    db.collection.dropIndexes( [ "a_1_b_1", "a_1", "a_1__id_-1" ] )
    

索引類型

Single Field 索引

  • 單字段索引
  • 對於單字段索引,升序降序並不重要,因為mongodb可以按任意方向遍歷索引

示例

db.collection.createIndex( { orderDate: 1 } )
  • 在 orderDate 字段上創建一個升序索引
  • 默認名稱orderDate_1

Compound 索引

  • 復合索引

  • 將多個字段組合成一個索引

  • 創建復合索引時,字段的順序非常重要

  • 整體上按第一個字段進行排序,對於按第一個字段排序並列的索引,再使用第二個字段進行排序

  • 查詢條件中必須包含索引的前綴字段

    例如以3個字段組成的索引,查詢條件中需包含第一個字段 或 第一個及第二個字段 或 全部三個字段

  • 復合索引中不能包含 hashed 索引

示例

db.collection.createIndex( { orderDate: 1, zipcode: -1 } )
  • 創建一個在 orderDate 字段進行升序排列,在 zipcode 字段進行降序排列的復合索引

Multikey 索引

  • 多鍵索引
  • 使用點表示法,對嵌套數組中的字段建立索引
  • mongodb會為數組中的每個元素創建單獨的 索引項
  • 允許查詢條件匹配數組的一個或多個元素來選擇符合條件的文檔
  • 如果索引字段包含數組元素,mongodb會自動創建一個多鍵索引

Geospatial 索引

  • 地理空間索引

Text 索引

  • 文本索引:對字符串內容進行查詢
  • 一般在 字符串類型字段 或 字符串數組類型字段 上創建文本索引
  • 使用文本索引查找時,不區分字母大小寫
  • 目前不支持中文文本索引,支持英語、法語、德語、俄語、西班牙語、土耳其語
  • 文本索引具有 sparse 屬性,忽略創建過程中的 sparse 選項
  • 文本索引支持 $text 查詢操作
  • 限制
    • 一個集合最多只能創建一個文檔索引
    • 排序操作 sort,不能使用文本索引中的排序
    • 復合文本索引中,如果在文本索引鍵之前包含其他鍵,則通過 $text 搜索時,查詢謂詞必須包含前面鍵的相等匹配條件
    • 只能通過索引名稱刪除文本索引

格式

db.collection.createIndex(
keys ,
options
)
  • keys

    • 類型:Document

    • 描述:text 類型的索引規范文檔

      • 單字段

        { field1: "text"}
        
      • 多字段

        { 
        	field1: "text",
        	field2: "text",
        	...
        }
        // 復合索引
        { 
        	field1: 1,
        	field2: "text",
        	...
        }
        
      • 全部字段

        $** 代表文檔中的所有字符串類型的字段

          { "$**": "text" }
        
  • options

    • weights
      • 類型:Document
      • 描述:
        • 包含字段和權重的文檔,指定字段的權重,默認值為1,可設定為 1-99999 之間的整數
        • 優先查詢權重大的字段,次之查詢權重小的字段
    • default_language
      • 類型:字符串
      • 描述
        • 對於文本索引,不同的語言有不同的分析規則
        • 默認值為 english
    • language_override
      • 類型:字符串
      • 描述
        • For text indexes, the name of the field, in the collection’s documents, that contains the override language for the document
        • 默認值為language
    • textIndexVersion
      • 類型:integer
      • 描述:指定文本索引的版本

示例

  • 創建文本索引

    db.reviews.createIndex( { comments: "text" } )
    
    db.reviews.createIndex(
       {
         subject: "text",
         comments: "text"
       }
     )
     
     db.reviews.createIndex( { "$**": "text" } )
    
  • 指定不同的權重

     db.reviews.createIndex(
     { "$**": "text" } ,
     { weights : {subject: 10, comments: 5}}
     )
    
    • 索引名$**_text

Hashed 索引

  • 哈希索引:使用字段值的哈希值來創建索引

  • 主要用在分片的片鍵上

  • 支持 非數組 單字段 索引,不支持多字段索引

    多字段索引報錯

    db.articles.createIndex({subject:"hashed",author:"hashed"})
    
    • "errmsg" : "Currently only single field hashed index supported."

    數組字段索引報錯

    db.articles.createIndex({arr:"hashed"})
    
    • "errmsg" : "Error: hashed indexes do not currently support array values",

    • creating a hashed index on a field that contains an array or attempting to insert an array into a hashed indexed field returns an error.

  • 不能設定唯一性約束,因為存在hash碰撞

    db.articles.createIndex({subject:"hashed"},{unique:true})
    
    • "errmsg" : "Currently hashed indexes cannot guarantee uniqueness. Use a regular index."
  • 創建哈希索引的字段,也可以同時創建其他索引

    不支持創建復合索引,但是同一個字段可以創建多個不同類型的索引

    db.articles.createIndex({subject:"hashed"})
    db.articles.createIndex({subject:"hashed",subject:"text"}) // 只會創建一個文本索引
    db.articles.createIndex({subject:"hashed",subject:1}) // 只會創建一個升序索引
    // 最終在 subject 字段上創建了3個不同類型的索引
    
  • 哈希索引支持相等查詢,不支持范圍查詢

  • 在使用哈希索引查詢時,mongodb 會自動計算,無需單獨計算

    4.0 版本開始,mongodb提供了 convertShardKeyToHashed() 方法,該方法使用相同的哈希計算方法,可用於查看鍵的哈希值

  • 類型為浮點數的字段不能創建哈希索引

    mongodb 哈希索引在計算之前會將浮點數截斷為64位的整數,例如 2.3、 2.2、 2.9 都被截斷為2進行計算

格式

db.collection.createIndex( { field: "hashed" } )

索引屬性

Unique 索引

  • 唯一性

Partial 索引

  • 局部性

Sparse 索引

  • 稀疏性

TTL 索引

  • 生命周期性(文檔在一段時間后會被mongodb自動刪除)

  • 一般在 Date類型的字段 或 包含Date類型元素的數組字段 上創建TTL索引,其他字段無效

  • 過期閾值的計算

    • 如果字段類型是 Date,則過期閾值是字段值日期加上指定的過期時間
    • 如果字段類型是包含 Date 類型元素的數組,則過期閾值是元素中最早的日期加上指定的過期時間
    • 如果非以上兩種類型,TTL 索引無效,文檔不會過期
  • expireAfterSeconds 設置為0,則過期時間就是日期字段的值

  • TTL 線程

    • mongod 中的后台線程,每隔60秒運行一次,用來讀取索引中的值並從集合中刪除過期的文檔
    • 不保證文檔過期后立即被刪除,文檔過期的時間和從數據庫中刪除的時間存在延遲(60s)
    • 當 TTL 線程處於活動狀態時,可以在 db.currentOp() 的輸出中看到刪除操作
  • 限制

    • 不能在 _id 字段上建立 TTL 索引

    • 不能通過改變 options 將非 TTL 索引變為 TTL 索引

    • 不能在固定集合中建立 TTL 索引,因為mongodb不能從固定集合中刪除文檔

    • 不能是復合索引,只能是單字段索引

格式

db.collection.createIndex(
    <keys>,
    {
    expireAfterSeconds: <integer>
    }
)

示例

文檔

db.ttl.insertMany([
{date:new Date("2020-08-13T17:50:00"), money:1},
{date:new Date("2020-08-13T17:52:00"), money:2},
{date:new Date("2020-08-13T17:54:00"), money:3},
])
db.ttl.createIndex({date:-1})
db.ttl.createIndex({date:1, money:-1})
db.ttl.createIndex({date:1},{expireAfterSeconds:10})
  • 在 ttl 集合中的 date 字段上創建3個索引
  • 有一個 TTL 索引,過期閾值為:date 日期加上指定過期時間
  • 結果是,到過期閾值時,文檔被依次刪除

修改過期時間

db.runCommand({
   collMod: <collection>,
   index:{
              keyPattern: <keys>,
              expireAfterSeconds: <integer>
    }
})

示例

db.ttl.insertMany([
{date:new Date("2020-08-13T18:08:00"), money:1},
{date:new Date("2020-08-13T18:09:00"), money:2},
{date:new Date("2020-08-13T18:10:00"), money:3},
])
db.runCommand({
	collMod:"ttl",
	index:{
		keyPattern:{date:1},
		expireAfterSeconds:60*60
	}
})

返回結果

{ "expireAfterSeconds_old" : 10, "expireAfterSeconds_new" : 3600, "ok" : 1 }

Hidden 索引

4.4 新增

  • 對查詢規划器不可見,不能用於查詢
  • 用來評估刪除索引的潛在影響,而不必實際刪除該索引。如果影響是負面的,用戶可以取消隱藏索引,而不必重新創建
  • 索引在隱藏時也會被維護,因此一旦不隱藏,就可以立即使用這些索引


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM